2012-05-22 25 views
1

我使用的代码:分裂在Perl字符串转换成数据库

$data_read=$port_obj->read($buffer); 
print "$data_read\n"; 

输出是这样的:

T=3420499518 A=914 B=97 C=49 D=436 E=428 F=863 G=34 H=771 I=214 J=493 K=165 

我希望把它在这:

$T,$A,$B,$C,$D,$E,$F,$G,$H,$I,$J,$K 

所以我可以将它写入MySQL数据库。我该怎么做 ?

我的数据库处理程序:

$query = "INSERT INTO myhouse (T,A,B,C,D,E,F,G,H,I,J,K) 
      VALUES ($T,$A,$B,$C,$D,$E,$F,$G,$H,$I,$J,$K)"; 

$query_handle = $connect->prepare($query); 

$query_handle->execute(); 
+5

你不应该在查询插值变量。改为使用[占位符](http://search.cpan.org/perldoc?DBI#Placeholders_and_Bind_Values)。 – TLP

+2

如果它们都是数字,那么没有太大的危险,但是应该完成验证它们都是数字。 –

回答

0

我喜欢这样说:

use strict; 
use warnings; 

my $data_read = "T=3420499518 A=914 B=97 C=49 D=436 E=428 F=863 G=34 H=771 I=214 J=493 K=165"; 
my %data = split(/\s+|=/, $data_read); 

my @cols = keys %data; 
my $cols = join(', ', @cols); 
my $placeholders = join(', ', ('?')x scalar @cols); 

my $query = "INSERT INTO table ($cols) VALUES ($placeholders)"; 
    # execute like this: 
# $dbh->do($query, undef, @data{@cols}); 

print "$query\n"; 
1

我不知道该把它们放入单独命名的变量是最好的选择,但客户永远是对的:

use strict; 
use warnings; 

my $data_read = "T=3420499518 A=914 B=97 C=49 D=436 E=428 F=863 G=34 H=771 I=214 J=493 K=165"; 

my $data = $data_read; 
$data =~ s/[A-KT]=//g; 

print "$data\n"; 

my($T,$A,$B,$C,$D,$E,$F,$G,$H,$I,$J,$K) = split /\s+/, $data; 

my $query = "INSERT INTO myhouse (T,A,B,C,D,E,F,G,H,I,J,K) VALUES\n" . 
      "($T,$A,$B,$C,$D,$E,$F,$G,$H,$I,$J,$K)"; 

print "$query\n"; 

print "\nAlternative:\n"; 
my(@list) = split /\s+/, $data; 
print "@list\n"; 

my $query2 = "INSERT INTO myhouse (T,A,B,C,D,E,F,G,H,I,J,K)\nVALUES(" . 
      join(",", @list) . ")"; 

print "$query2\n"; 

当这个片段它会生成:

3420499518 914 97 49 436 428 863 34 771 214 493 165 
INSERT INTO myhouse (T,A,B,C,D,E,F,G,H,I,J,K) VALUES 
(3420499518,914,97,49,436,428,863,34,771,214,493,165) 

Alternative: 
3420499518 914 97 49 436 428 863 34 771 214 493 165 
INSERT INTO myhouse (T,A,B,C,D,E,F,G,H,I,J,K) 
VALUES(3420499518,914,97,49,436,428,863,34,771,214,493,165) 

脚本的后半部分显示了一个更简单的ALT使用数组来保存读取的值。

显然,如果您愿意,您可以检查是否将值分配给了所有变量以及其他此类错误检查。

+0

我在想,使用哈希将是最佳的,但我不确定字段名称可以插入占位符。 'my%data = map {split/= /} split'',$ data; .... $ dbh-> execute(键%data,values%data);'我相信虽然哈希不保存顺序,但它们在键和值之间保持相同的无序。 – TLP

+0

我隐约想知道如何使用散列,但决定阵列的保证位置性质适合位置输入。您必须以正确的顺序AFAIK将密钥放入准备好的语句中,然后将值输入到列表中。我认为''dbh-> execute()'符号应该在预期值的数目和提供的数目之间产生不匹配; Perl没有办法从一个列表中区分两个列表,而SQL也不提供合适的机制。 –

+0

Tnx Jonathan Leffler ..它的工作原理...最好的版本看起来像“替代” - 还有一个小问题: –

5

您应该将数据值存储在散列中,在准备好的SQL语句中使用占位符,并将散列片传递给execute方法。

代码看起来像扩展上评论乔纳森·莱弗勒的回答这个

my $data_read = 'T=3420499518 A=914 B=97 C=49 D=436 E=428 F=863 G=34 H=771 I=214 J=493 K=165'; 

my %data = $data_read =~/([A-Z0-9]+)/g; 

my $query_handle = $connect->prepare(<<SQL); 
INSERT INTO myhouse (T,A,B,C,D,E,F,G,H,I,J,K) 
VALUES (?,?,?,?,?,?,?,?,?,?,?,?) 
SQL 

$query_handle->execute(@data{ qw/ T A B C D E F G H I J K/}); 
2

perldoc keys告诉我们:

哈希的密钥在一个明显的随机顺序返回。所述 实际随机的顺序是受试者在Perl, 未来版本的改变,但作为valueseach 函数产生(假定散列未被修改)它保证是相同的顺序。

(重点煤矿)这意味着我们可以使用哈希来收集所有字段名及其相关值,而不需要明确地列举他们在代码:

#!/usr/bin/env perl 

use 5.010; 
use strict; 
use warnings; 

my $in = 'T=3420499518 A=914 B=97 C=49 D=436 E=428 F=863 G=34 H=771 I=214 J=493 K=165'; 

my %data = $in =~ /([A-Z])=([0-9]+)/g; 

my $query = 'INSERT INTO myhouse (' . join(',', keys %data) 
      . ') VALUES (' . join(',', values %data) . ')'; 

say $query; 

(注意,TLP在原始问题的评论中提到,这是只有安全,因为填充%data的正则表达式保证我们所有的密钥都将是单个大写字母,并且值将只包含英文数字如果有任何可能恶意输入可能导致中的不受控制的键或值,那么您需要对字段名称进行硬编码并为值使用占位符,除非您想要访问little Bobby Tables。)