linux - DBD::Pg::st 执行失败:错误: "$1"处或附近的语法错误

标签 linux perl postgresql dbi

尝试使用 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 注入(inject),但由于某种原因我遇到了语法错误。

有人遇到过这个吗?

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

最佳答案

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 的使用使列名可以安全地进行插值。如果您要以这个简单的 prepareexecutefinish 序列结束,那么您可能只想使用 do相反。

关于linux - DBD::Pg::st 执行失败:错误: "$1"处或附近的语法错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16726515/

相关文章:

linux - 我如何将 yacc 更改为 bison (LFS)

c - 如何在2个进程之间分配system-V共享内存

regex - 一个简单的Perl正则表达式保证永远不会匹配字符串?

linux - TSS_WELL_KNOWN_SECRET 的值是多少

linux - 我的虚拟服务器 Linux 无法连接到互联网

perl - 有没有办法在催化剂中使用测试数据库

perl - Perl 有类似 Java/PHP 文档的东西吗?

mysql - 驻留在 mysql 列中的字符串无法插入到 redshift 上完全相同的列中,指出 DDL 长度错误

arrays - 在数组子对象上创建 Postgres JSONB 索引

ruby-on-rails - 服务器需要 postgres,即使我在其上使用 sqlserver