2013-02-16 92 views
3

我正在嘗試編寫接受SQL INSERT語句的綁定的Perl代碼,並確定可能導致INSERT被錯誤數據拒絕並修復它們的問題。爲此,我需要獲取並解釋列元數據。解釋Perl DBI MySQL column_info()

$ 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,爲什麼這兩種風格?

我可以欣賞記錄(更不用說執行)數據庫通用接口的難度。但是我想知道是否有人知道使用DBI的特定於MySQL的參考手冊?

UPDATE 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秒;現在我只是揮舞着約猜測。)

更新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返回的內容。現在我可以看到我有四個選擇學習數據類型,所以讓我們看看是否有任何代碼記錄。

更新3:

DBI Recipes是一個非常好的輔助CPAN DBI文檔有關檢索信息返回到Perl的

(特別是{選擇|取} {行| |所有} _ {中hash數組}方法。)
+0

https://metacpan.org/module/DBD::mysql可能是一個很好的開始。 – Perleone 2013-02-16 20:12:08

+0

謝謝 - 如果我正確地閱讀它,那麼STATEMENT HANDLES部分將與我最相關。但是這個技術似乎要求你首先在表上執行一個SELECT *。 (沒有檢查過它是否可以在空的表上運行。)對整個表使用'column_info'方法似乎是更好的方法,這就是爲什麼我更喜歡學習如何使用它。 – Chap 2013-02-16 23:11:42

回答

1

這將幫助您確定data_types的值。我通常使用data_type來確定如何根據類型處理列。

然後您需要查看下面的MySQL數據類型密鑰並獲取哈希值。然後查看下面的DBI表並匹配數據名稱以獲取數據類型值。例如:一個BIGINT是匹配SQL_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]的方式驅動它們的天然類型映射到這些標準類型變化很大。與其中一種類型不匹配的本機類型可能會映射到正式保留供Perl DBI使用的範圍:-9999至-9000。

+0

您在編寫「data_type」/「DATA_TYPE」/「數據類型」時的變化令我感到困惑。我試圖從'DATA_TYPE'(一個整數,在我的情況下是4)向後走。 '4 => SQL_INTEGER',但我沒有看到如何從那裏進入'%DBD :: mysql :: db :: ANSI2db'哈希。我想我誤解了你的意思。 – Chap 2013-02-18 20:20:58

+0

'使用DBI qw(:sql_types);'根據http://search.cpan.org/dist/DBI/DBI.pm,將導入一堆形式爲SQL_ *的常量,這些常量等同於這些整數。允許我寫'if($ the_data_type == SQL_INTEGER){...}'。 – Chap 2013-02-19 00:57:29

+0

您的DATA_TYPE的值等於第二個列表中常見類型的標準值。您可以測試以查看是否$ name [4] – JParadiso 2013-02-19 01:32:34