我正在编写一个perl脚本,它从文件中读取社会安全号码,在多个表中查找信息并输出到分隔文件。我用PERL 5写作并与IBM informix打交道。我觉得这是我的REGEX问题。我得到以下错误的多行:
DBD :: Informix :: st执行失败:SQL:-1213:数字转换过程中的字符在./corylist.pl第61行第461行失败。 DBD :: Informix :: st fetchrow_array失败:SQL:-400:尝试取消打开游标。在./corylist.pl第63行,第461行。
有人可以向我推正正确的方向吗?谢谢!
while(<IN>) {
$id = $_;
chomp $id;
$id =~ m/^\d{3}-\d{2}-\d{4}$/;
#print "$id\n";
$STMT = <<EOF;
select i.ss_no,
i.fullname, i.firstname,i.lastname,i.addr_line1,i.addr_line2,i.city,i.st,i.zip,r.res_ctry,r.res_cty,
i.phone,NVL(aa.phone," ") cell,NVL(a.line1," ") stuemail,NVL(pa.line1," ") peremail
from id i,
prof r,
outer aa_rec a,
outer aa_rec aa,
outer aa_rec pa
where i.ss_no = $id
and i.id = r.id
and i.decsd <> "Y"
and a.id = i.id and a.aa = "EML" and a.end_date is null
and pa.id = i.id and pa.aa = "OEML" and pa.end_date is null
and pa.beg_date = (select max(beg_date) from aa_rec where aa = "OEML" and id=$id and end_date is null)
and aa.id = i.id and aa.aa = "CELL" and aa.end_date is null
group by ss_no,fullname,firstname,lastname,addr_line1,addr_line2,city,st,zip,res_ctry,res_cty,phone,cell,stuemail,peremail
order by fullname, ss_no
EOF
$sth = $db1->prepare($STMT);
$sth->execute();
while (($id,$fullname,$fname,$lname,$addr1,$addr2,$city,$st,$zip,$ctry,$cnty,$phone,$cell,$stuemail,$peremail) = $sth->fetchrow_array()) {
$x = $id." | ". $fullname." | ";
$x .= $fname." | ".$lname." | ".$addr1." | ".$addr2." | ".$city." | ".$st." | ".$zip." | ".$ctry." | ".$cnty." | ";
$x .= $phone." | ".$cell." | ".$stuemail." | ".$peremail." | \n";
print $out_fh $x;
}
答案 0 :(得分:4)
你的正则表达式很好,但它没有做任何事情。
$id =~ m/^\d{3}-\d{2}-\d{4}$/;
如果$id
与模式匹配,则该行将为true。它没有别的。
字符到数字转换过程失败
错误消息显示您的数据库想要一个数字,但得到的东西无法转换它得到的东西。由于您在查询中使用$id
,因此必须使用短划线。因此,假设您的SSN是某种整数,那就省了。
摆脱错误消息的最简单方法是删除任何不是数字的内容。这将消除破折号-
以及其他人们想要输入的内容。
while ( my $id = <IN>) {
chomp $id;
$id =~ s/\D//g; # remove any non-digits
# ...
}
现在你可以进行插入了。但是,如果没有适当的引用,您应该直接将变量直接写入SQL中来插入数据。那是an invitation for SQL injection。相反,请使用placeholders。
my $sql = "SELECT * FROM foo WHERE bar=?";
现在当您execute
语句prepare
时,您传递了$id
。
my $sth = $dbh->prepare($sql);
$sth->execute($id);
如果您正在处理大型文件,最好使用fetchrow_arrayref
或fetchrow_hashref
代替fetchrow_array
,因为所有变量的复制都是如此很贵。另请查看this presentation以了解有关快速使用DBI的更多信息。
您可能希望查看SSN::Validate以实际验证社会安全号码。如果您使用它,似乎您不需要进行上面建议的清理。
您还可以查看Text::CSV以获得创建CSV输出的更简洁方法。