2013-05-24 16 views
5

PostgreSQLでPerlとDBIを使用して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 

関連するコードは、だから私は、0に「状況」を更新しようと、SQLインジェクションを防ぐために、executeメソッドを使用して、私はいくつかの構文エラーを取得していますよ

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; 

です理由。

誰でもこれに参加できますか?

[email protected] ~]# 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 

[email protected] ~]# 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 

答えて

9

PostgreSQLでは、あなたがそう誰かがプレースホルダに番号を付けるためにあなたの?プレースホルダを翻訳された位置?プレースホルダの上に番号が付けプレースホルダ($1$2を、...)を使用することを好みます。エラーメッセージの

UPDATE instances SET $1 = $2 

UPDATE instances SET ? = ? 

のように終わる:あなたのSQLが理由です。

実際の問題は、識別子(表名、列名など)にプレースホルダを使用できないことです。値のプレースホルダのみを使用できます。 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を使用してください。

+0

はい、これで問題は解決します。ありがとうございました! –

+0

+1:_あなたは識別子(表名、列名、...)にプレースホルダを使用できません_ ...ありがとう! –

関連する問題