2013-02-16 72 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