2016-09-22 10 views
-1

を持っている:誰もがこのクエリと間違っているものを私に伝えることができます私は、クエリの問題

$query = "INSERT INTO ideas_tbl (idea, desc) VALUES ('$idea', '$desc')"; 
+0

watsエラー? –

+1

'desc'はSQLのキーワードです(' ORDER BY'と考えてください)。私はシンプルなタイポグラフィのような質問を終わらせることに投票します。 –

+0

[SQLインジェクション攻撃](https://en.wikipedia.org/wiki/Sql_injection_attack)に脆弱です。これと他の多くの問題を回避するには、[bind parameters](https://metacpan.org/pod/DBI#Placeholders-and-Bind-Values)を使用してください。 – Schwern

答えて

0

As @GordonLinoff mentioned in a comment問題がdescでは、SQLキーワードです。そのように使用されると、SQLサーバーはそれを列名ではなく構文の一部として見て、混乱します。 SQLキーワードのリストはサーバーごとに異なりますが、here's a good baseline list from SQLiteです。

2つの解決策があります。まず、"で列を引用します。一部のデータベースは`(MySQL)または[](Microsoft)を使用しますが、"はSQL標準です。準拠していないデータベースは、MySQL has ANSI_QUOTESのように"標準をサポートするように構成できます。

これはまた、balanced quoting operators(これはPerlであると仮定します)を使用して、引用符をエスケープするか、または私の推奨するオプションを意味します。

$query = qq[INSERT INTO ideas_tbl (idea, "desc") VALUES ('$idea', '$desc')]; 

このオプションが気に入らない理由は、その列が使用されるたびにそれを覚えておいてくださいということです。より良いオプションは、列を "description"のようなものにリネームすることです。


ここでセキュリティホールについて説明します。変数をクエリ文字列に直接入力したため、コードはSQL Injection Attackに脆弱です。これは最も一般的なセキュリティホールの1つです。 $ideaまたは$descがユーザーの入力に由来する場合、巧みな人は、引用符から飛び出してより多くのSQLとして解釈されるデータを作成できます。 $desc = "Our prices can't be beat!"

すべての種類の引用を行うことはできますが、完全に無効にしてコードを少しスピードアップするには、prepared statements and bind parametersを使用してください。ここでは、これがPerlでDBIを使用していると仮定しています。

my $sth = $dbh->prepare(q{ 
    INSERT INTO ideas_tbl 
      (idea, description) 
    VALUES (?, ? ) 
}; 
$sth->execute($idea, $desc); 
もう1つの利点は、このステートメントハンドルを再利用して、再コンパイルする必要がないためです。あなたがアイデアのリストをループしていたように。

for my $idea (@ideas) { 
    $sth->execute($idea->{idea}, $idea->{desc}); 
} 

最後に、私はあなたのクエリはあなたが質問をしている理由である障害が発生したときに、エラーメッセージを取得していない疑いがあります。残念ながら、DBIはデフォルトでSQLエラーをエラーとして扱いません。すべてのクエリの後にor dieを忘れた場合、エラーは発生しません。

これを避けるには、(最高)またはそれ以降に接続するときにRaiseErrorをオンにします。

my $dbh = DBI->connect($dsn, $user, $pass, { RaiseError => 1 }); 

or 

$dbh->RaiseError(1); 

ここで失敗したクエリはすべてエラーを発生させます。すべてのクエリにor die "Something failed because $DBI::errstr"を覚えておく必要はありません。

関連する問題