尝试使用Perl和DBI在PostgreSQL中设置一个值,从而设置DBD :: Pg。
我收到一个奇怪的错误。
2013-05-23 19:02:36.641139500 updating status to 0
2013-05-23 19:02:36.641410500 DBD::Pg::st execute failed: ERROR: syntax error at or near "$1"
2013-05-23 19:02:36.641418500 LINE 1: UPDATE instances SET $1 = $2
2013-05-23 19:02:36.641423500 ^ at /usr/lib/perl5/vendor_perl/Mitel/MslRest/mbg.pm line 161.
2013-05-23 19:02:36.642425500 [Thu May 23 19:02:36 2013] [error] DBD::Pg::st execute failed: ERROR: syntax error at or near "$1"
2013-05-23 19:02:36.642438500 LINE 1: UPDATE instances SET $1 = $2
2013-05-23 19:02:36.642443500 ^ at /usr/lib/perl5/vendor_perl/Mitel/MslRest/mbg.pm line 161.
2013-05-23 19:02:36.642447500
相关代码是
my $sql = "UPDATE instances SET ? = ?";
my $dbh = Mitel::tug::getdbh();
$dbh->begin_work;
my $sth = $dbh->prepare($sql);
unless ($sth) {
return $self->internal_error("prepare failed: " . $dbh->errstr);
}
foreach my $propname (sort keys %{ $raw_data }) {
my $propval = $raw_data->{$propname};
print STDERR "updating $propname to $propval\n";
if (! $sth->execute($propname, $propval)) {
$dbh->rollback;
$sth->finish;
return $self->internal_error("execute: " . $dbh->errstr);
}
}
$dbh->commit;
$sth->finish;
所以我试图将“status”更新为0,使用execute方法来阻止sql注入,但由于某种原因我收到语法错误。
有人碰到这个吗?
root@miketug2 ~]# perl -v
This is perl, v5.10.1 (*) built for i386-linux-thread-multi
perl-DBD-Pg-2.15.1-4.el6_3.i686
postgresql84-server-8.4.14-1PGDG.rhel6.i686
root@miketug2 ~]# uname -a
Linux miketug2 2.6.32-279.22.1.el6.i686 #1 SMP Wed Feb 6 00:31:03 UTC 2013 i686 i686 i386 GNU/Linux
答案 0 :(得分:9)
PostgreSQL更喜欢您使用编号占位符($1
,$2
,...)而不是位置?
占位符,因此有人正在将您的?
占位符翻译为数字占位符;这就是你的SQL:
UPDATE instances SET ? = ?
结束为:
UPDATE instances SET $1 = $2
在错误消息中。
现在真正的问题是你不能使用占位符作为标识符(表名,列名,......),你只能使用占位符来表示值。你不能说SET ? = ?
,你必须以其他方式提供列名,可能是通过字符串插值。这意味着您必须将循环内的prepare
移动到以下内容:
foreach my $propname (sort keys %{ $raw_data }) {
my $prop = $dbh->quote_identifier($propname);
my $propval = $raw_data->{$propname};
my $sth = $dbh->prepare("UPDATE instances SET $prop = ?");
$sth->execute($propval);
$sth->finish();
}
您的真实代码当然会包含错误处理。请注意使用quote_identifier
使列名称对插值安全。如果您最终会使用这个简单的prepare
,execute
,finish
序列,那么您可能只想使用do
。