我有一个具有以下结构的MySQL表。
alid bigint(20),
ndip varchar(20),
ndregion varchar(20),
occ_num int(3),
Delta_Flag int(1)
从表中选择数据后,我将获取所有引用的数据并作为字符串值。
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use FindBin;
use lib $FindBin::Bin;
use Database;
my $pwd = $FindBin::Bin;
my $db = Database->new( 'mysql', "$pwd/config.ini" );
my $db1 = Database->new( 'mysql', "$pwd/config2.ini" );
my @tables = qw( AutoTT_AlarmStatus_Major1 );
for my $table ( @tables ) {
my $query_select = "SELECT alid, ndip, ndregion, occ_num, Delta_Flag FROM $table LIMIT 1";
my $result = $db->db_get_results( $query_select );
print Dumper( $result );
for my $item ( @{$result} ) {
# Here I want to prepare, bind and insert this data
# into other table with same structure
}
}
sub db_get_results {
my $self = shift;
my $qry = shift;
my $sth = $self->{dbh}->prepare( $qry );
$sth->execute();
my @return = ();
while ( my @line = $sth->fetchrow_array ) {
push @return, \@line;
}
return \@return;
}
$VAR1 = [
[
'1788353',
'10.34.38.12',
'North Central',
'1',
'1'
]
];
为什么DBI
隐式将所有整数转换为字符串?
答案 0 :(得分:6)
正如@choroba在他的回答中指出的那样,不是DBI正在对数据做任何事情。它只是通过驱动程序模块(在您的情况下为DBD :: mysql)返回。
在DBI文档的General Interface Rules & Caveats部分中,它说:
大多数数据作为字符串返回到Perl脚本。 (空值返回为undef。)这允许处理任意精度数值数据而不会损失准确性。请注意,当字符串用作数字时,Perl可能无法保持相同的准确度。
我在将perl配置为支持64位整数的常见日子之前写了这篇文章,并且长双浮点类型不常见。这些天我建议驱动程序返回最“自然”Perl类型的值,不会有数据丢失的风险。
对于某些可能很难实现的驱动程序,特别是那些支持从单个句柄返回多个结果集的数据集,如DBD :: mysql那样。
我浏览了DBD::mysql docs,但没有看到任何关于这个主题的提及,所以我看了the relevant code我可以看到当前的DBD :: mysql 是将数字作为数字返回。还有很多references to recent changes in this area in the Change log。
也许您正在使用旧版本的DBD :: mysql并且应该升级。
答案 1 :(得分:1)
这就是MySQL的DBD驱动程序的工作方式。其他数据库可能表现不同。例如,在SQLite中,数字仍为数字:
#!/usr/bin/perl
use warnings;
use strict;
use DBI;
use Data::Dumper;
my $dbh = 'DBI'->connect('dbi:SQLite:dbname=:memory:', q(), q());
$dbh->do('CREATE TABLE t (id INT, val VARCHAR(10))');
my $insert = $dbh->prepare('INSERT INTO t VALUES (?, ?)');
$insert->execute(@$_) for [ 1, 'foo' ], [ 2, 'bar' ];
my $query = $dbh->prepare('SELECT id, val FROM t');
$query->execute;
while (my $row = $query->fetchrow_arrayref) {
print Dumper($row);
}
__END__
$VAR1 = [
1,
'foo'
];
$VAR1 = [
2,
'bar'
];
答案 2 :(得分:0)
一般来说,这不是DBI所做的。正如已经指出的那样,DBI系统的许多数据库驱动程序(DBD :: xy)将数字转换为字符串。 AFAIK无法避免这种情况。
你可以做的是询问语句句柄是否有相应的本机类型,或者(在你的情况下更容易),你的结果集列是否是mysql-DB中的数字。这是一个例子
鉴于此基本数据库:
mysql> create table test (id INT,text VARCHAR(20));
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO test VALUES (1,'lalala');
Query OK, 1 row affected (0.00 sec)
您可以使用特定于驱动程序的字段' mysql_is_num'来查找列是否为数字:
引用布尔值数组; TRUE表示相应列包含数值。 (来自DBD::mysql)
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
use DBI;
use DBD::mysql;
use Data::Dumper;
my $dsn = "DBI:mysql:database=test;host=localhost";
my $dbh = DBI->connect($dsn,'user','pass') or die "$!";
my $sql = "SELECT * FROM test WHERE id = ?";
my $sth = $dbh->prepare($sql);
$sth->execute(1);
my $num_fields = $sth->{'NUM_OF_FIELDS'};
my $num_mask = $sth->{'mysql_is_num'};
my $result;
my $cnt = 0;
while (my $line = $sth->fetchrow_arrayref){
for (my $i = 0; $i < $num_fields; $i++){
if ($num_mask->[$i]){
$line->[$i] + 0;
}
$result->[$cnt] = $line;
}
$cnt++;
}
print Dumper($result);
我希望这会有所帮助。因为它写得很匆忙,请原谅我的风格。当然,我对任何建议持开放态度。