3

私は、SQL INSERT ステートメントのバインドを受け入れる Perl コードを作成しようとしています。また、不適切なデータに対して INSERT が拒否される原因となる可能性のある問題を特定し、修正します。これを行うには、列のメタデータを取得して解釈する必要があります。

$dbh->column_info メソッドは情報をコード化された形式で返します。私は公式の CPAN ドキュメントを熟読しましたが、まだ混乱しています。

my $sth_column_info
        = $dbh->column_info( $catalog, $schema, $table, undef );
    my $columns_aoh_ref = $sth_column_info->fetchall_arrayref(
        {   COLUMN_NAME      => 1,
            DATA_TYPE        => 1,
            NULLABLE         => 1,
            ORDINAL_POSITION => 1,
            COLUMN_DEF       => 1,
        }
    );
    say $table;
    for my $href (@$columns_aoh_ref) {
        my @list;
        while ( my ( $k, $v ) = each %$href ) {
            push @list, "$k=" . ( $v // 'undef' );
        }
        say join '|', @list;
    }

出力は次のとおりです。

dw_phone
NULLABLE=0|COLUMN_DEF=undef|DATA_TYPE=4|ORDINAL_POSITION=1|COLUMN_NAME=phone_id
NULLABLE=0|COLUMN_DEF=undef|DATA_TYPE=4|ORDINAL_POSITION=2|COLUMN_NAME=phone_no
NULLABLE=1|COLUMN_DEF=undef|DATA_TYPE=4|ORDINAL_POSITION=3|COLUMN_NAME=phone_ext
NULLABLE=0|COLUMN_DEF=undef|DATA_TYPE=1|ORDINAL_POSITION=4|COLUMN_NAME=phone_type
NULLABLE=0|COLUMN_DEF=undef|DATA_TYPE=1|ORDINAL_POSITION=5|COLUMN_NAME=phone_location
NULLABLE=1|COLUMN_DEF=undef|DATA_TYPE=1|ORDINAL_POSITION=6|COLUMN_NAME=phone_status
NULLABLE=0|COLUMN_DEF=undef|DATA_TYPE=11|ORDINAL_POSITION=7|COLUMN_NAME=insert_date
NULLABLE=0|COLUMN_DEF=undef|DATA_TYPE=11|ORDINAL_POSITION=8|COLUMN_NAME=update_date

たとえば、データ型コードから文字列へのマッピングはどこにありますか? DATA_TYPE、TYPE_NAME、または SQL_DATA_TYPE を使用する必要がありますか? NULLABLE または IS_NULLABLE を使用する必要がありますか? なぜ 2 つのフレーバーがあるのですか?

データベース用のユニバーサル インターフェイスを文書化する (実装するどころか) ことの難しさは理解できます。しかし、MySQL 固有の DBI を使用するためのリファレンス マニュアルを知っている人はいますか?

更新 1:

ハッシュではなく配列を使用してすべての情報を取得することで、より多くの光を当てようとしました:

    my $sth_column_info
        = $dbh->column_info( $catalog, $schema, $table, undef );

    my $aoa_ref = $sth_column_info->fetchall_arrayref; # <- chg. to arrayref, no parms
    say $table;
    for my $aref (@$aoa_ref) {
        my @list = map $_ // 'undef', @$aref;
        say join '|', @list;
    }

今、私はそこに潜在的に有用な情報がたくさん混ざっているのを見ることができます.

dw_contact_source
undef|dwcust1|dw_contact_source|contact_id|4|BIGINT|20|undef|undef|10|0|undef|undef|4|undef|undef|1|NO|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|1|bigint(20)|undef|0
undef|dwcust1|dw_contact_source|company_id|4|SMALLINT|6|undef|undef|10|0|undef|undef|4|undef|undef|2|NO|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|1|smallint(6)|undef|0
undef|dwcust1|dw_contact_source|contact_type_id|4|TINYINT|4|undef|undef|10|0|undef|undef|4|undef|undef|3|NO|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef||tinyint(4)|undef|0
undef|dwcust1|dw_contact_source|insert_date|11|DATETIME|19|undef|0|undef|0|undef|undef|9|-79|undef|4|NO|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef||datetime|undef|0
undef|dwcust1|dw_contact_source|update_date|11|DATETIME|19|undef|0|undef|0|undef|undef|9|-79|undef|5|NO|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef|undef||datetime|undef|0

だから私の質問は次のようになります:

  • これらのメタデータの対応する名前/説明を取得するにはどうすればよいですか?
  • fetchall_arrayref整数ではなく記号を使用して、必要なものだけを使用するにはどうすればよいですか? (私はfetchall_arrayref([qw/COLUMN_NAME DATA_TYPE/])すべてundefの s を試してみましたが、今は推測に苦しんでいます。)

更新 2:

DBD::mysql.pm を調べていると、非常に興味深い配列が見つかりました。

my @names = qw(                                                                                                                                             
    TABLE_CAT TABLE_SCHEM TABLE_NAME COLUMN_NAME                                                                                                            
    DATA_TYPE TYPE_NAME COLUMN_SIZE BUFFER_LENGTH DECIMAL_DIGITS                                                                                            
    NUM_PREC_RADIX NULLABLE REMARKS COLUMN_DEF                                                                                                              
    SQL_DATA_TYPE SQL_DATETIME_SUB CHAR_OCTET_LENGTH                                                                                                        
    ORDINAL_POSITION IS_NULLABLE CHAR_SET_CAT                                                                                                               
    CHAR_SET_SCHEM CHAR_SET_NAME COLLATION_CAT COLLATION_SCHEM COLLATION_NAME                                                                               
    UDT_CAT UDT_SCHEM UDT_NAME DOMAIN_CAT DOMAIN_SCHEM DOMAIN_NAME                                                                                          
    SCOPE_CAT SCOPE_SCHEM SCOPE_NAME MAX_CARDINALITY                                                                                                        
    DTD_IDENTIFIER IS_SELF_REF                                                                                                                              
    mysql_is_pri_key mysql_type_name mysql_values                                                                                                           
    mysql_is_auto_increment                                                                                                                                 
);

これらは、fetchall_arrayref によって返されるものに正確に対応します。これで、データ型を学習するための4 つの選択肢があることがわかりました。コードのいずれかが文書化されているかどうかを見てみましょう。

更新 3:

DBI Recipesは、情報を取得して Perl に戻すことに関する CPAN DBI ドキュメント (特に {select|fetch}{row|all}_{hash|array} メソッド) の非常に優れた付属物です。

4

1 に答える 1

1

これは、data_types の値を決定するのに役立ちます。通常、data_type を使用して、その型に基づいて列を処理する方法を決定します。

次に、以下の MySQL データ型キーを見て、ハッシュ値を取得する必要があります。次に、以下の DBI テーブルを見て、データ名を照合してデータ型の値を取得します。例: BIGINT は SQL_INTEGER と一致する INTEGER タイプであるため、DATA_TYPE 値は 4 です。

DBD::MySQL
### ANSI datatype mapping to mSQL datatypes
%DBD::mysql::db::ANSI2db = ("CHAR"          => "CHAR",
            "VARCHAR"       => "CHAR",
            "LONGVARCHAR"   => "CHAR",
            "NUMERIC"       => "INTEGER",
            "DECIMAL"       => "INTEGER",
            "BIT"           => "INTEGER",
            "TINYINT"       => "INTEGER",
            "SMALLINT"      => "INTEGER",
            "INTEGER"       => "INTEGER",
            "BIGINT"        => "INTEGER",
            "REAL"          => "REAL",
            "FLOAT"         => "REAL",
            "DOUBLE"        => "REAL",
            "BINARY"        => "CHAR",
            "VARBINARY"     => "CHAR",
            "LONGVARBINARY" => "CHAR",
            "DATE"          => "CHAR",
            "TIME"          => "CHAR",
            "TIMESTAMP"     => "CHAR"
           );

DBI.pm TYPE TYPE 属性には、それぞれのデータ型の国際標準値を表す整数値の配列への参照が含まれています。整数の配列の長さは、元のステートメント内で選択された列の数と同じであり、前に示した NAME 属性の例と同様の方法で参照できます。

一般的なタイプの標準値は次のとおりです。

SQL_CHAR             1
SQL_NUMERIC          2
SQL_DECIMAL          3
SQL_INTEGER          4
SQL_SMALLINT         5
SQL_FLOAT            6
SQL_REAL             7
SQL_DOUBLE           8
SQL_DATE             9
SQL_TIME            10
SQL_TIMESTAMP       11
SQL_VARCHAR         12
SQL_LONGVARCHAR     -1
SQL_BINARY          -2
SQL_VARBINARY       -3
SQL_LONGVARBINARY   -4
SQL_BIGINT          -5
SQL_TINYINT         -6
SQL_BIT             -7
SQL_WCHAR           -8
SQL_WVARCHAR        -9
SQL_WLONGVARCHAR   -10

これらの数値はかなり標準的ですが、[61] ドライバーがネイティブ型をこれらの標準型にマップする方法は大きく異なります。これらの型の 1 つにうまく対応しないネイティブ型は、Perl DBI で使用するために公式に予約されている範囲 (-9999 か​​ら -9000) にマップされる場合があります。

于 2013-02-18T05:46:32.037 に答える