3

そのため、私はしばらくの間、多くのプロジェクトでプリペアドステートメントを使用しており、MySQLデータベースと対話するための非常にクリーンな方法でしたが、今日、奇妙な問題に遭遇しました。

私のプリペアドステートメントはSQLステートメントに'を追加し始めました、そして私の人生の間、私は理由がわかりません...

だからここにコードがあります:

<?php

    $sortby="ORDER BY submit_date DESC";
    $offset = 3;

    $sql = "SELECT img_id, img_name, submit_date FROM tbl_images WHERE img_active='y' :sortby LIMIT :offset, 9";

    $stmt = $this->_db->prepare($sql);
    $stmt->bindParam(":sortby", $sortby, PDO::PARAM_STR);
    $stmt->bindParam(":offset", $offset, PDO::PARAM_INT);
    $stmt->execute();

?>

上記は何も返さないので、データベースログを見ると、クエリは次のようになります。

SELECT img_id, img_name, submit_date FROM tbl_images WHERE img_active='y' 'ORDER BY submit_date DESC' LIMIT 3, 9

「ORDERBYsubmit_dateDESC」の周りに''の余分なセットを配置したようですが、オフセットの周りにはまだありませんか?

誰かが私を怒らせているので問題を見つけることができますか:)

前もって感謝します!

解決策、投稿してくれた人たちのおかげで、あなたは正しかったです。私はフィールドをパーツに分割し、魅力のように機能します。以下のコードソリューション:

<?php

    $sortfield="submit_date";
    $sortway="DESC"
    $offset = 3;

    $sql = "SELECT img_id, img_name, submit_date FROM tbl_images WHERE img_active='y' ORDER BY :sortfield :sortway LIMIT :offset, 9";

    $stmt = $this->_db->prepare($sql);
    $stmt->bindParam(":sortfield", $sortfield, PDO::PARAM_STR);
    $stmt->bindParam(":sortway", $sortway, PDO::PARAM_STR);
    $stmt->bindParam(":offset", $offset, PDO::PARAM_INT);
    $stmt->execute();

?>
4

3 に答える 3

2

次のドキュメントをご覧くださいmysqli_stmt::prepare

マーカーは、SQLステートメントの特定の場所でのみ有効です。たとえば、INSERTステートメントのVALUES()リスト(行の列値を指定するため)、またはWHERE句の列との比較で比較値を指定することができます。

基本的に、クエリの構造的なものをバインドされたパラメータにすることはできません。この方法で送信できるのはデータのみです。

PDOのプリペアドステートメントは、効果的に同じように機能します。ただし、あなたの場合、PDOは「エミュレート準備」モードで実行されているため少しばかげています(これはデフォルトですが、PDOを最大限に活用するにはオフにする必要があります)。クエリとデータを別々にサーバーに送信するのではなく、基本的にすべての置換自体を実行します。データが文字列であることがわかり、「ああ、文字列:これを引用符で囲む必要があります」と考えます。したがって、最終的には不正な形式のクエリになります。

解決策は、バインドされたパラメーターを使用してクエリの構造部分を構築しないことです。それらを連結で自分自身に置き換えるか、(そしてこれはより良いです)異なる設定のための代替クエリ文字列を持っています。これが最も安全な方法です。連結を伴うものはすべて、不安のレシピです。

ああ、PDOエミュレートをオフにして準備をオフにします!

于 2012-10-03T19:26:42.593 に答える
1

PDOでは、WHERE句またはON句の外部でプリペアドステートメントバインディング変数の置換を使用しないでください。これを行うと、任意の文字列が引用符で囲まれます(必要に応じて)。$ offset整数バインディングは機能する可能性がありますが、実行しないでください。値を文字列に置き換えるだけです(有効な値のホワイトリスト配列と比較した後)。

  $sql = "SELECT img_id, img_name, submit_date FROM tbl_images WHERE img_active='y' $sortby LIMIT $offset, 9";
于 2012-10-03T19:19:49.133 に答える
1

$sortbyエスケープおよび引用符で囲まれたSQLリテラルとしてバインドするのではなく、文字列補間を行います。

(ただし、信頼できないSQLフラグメントを補間しないように注意してください!)

パラメータバインディングは、リテラル値をクエリに置き換えるためのものであり、通常、プレーンな数値または文字列を意味します。パラメータは、SQL識別子(テーブル名や列名など)用でも構文要素用でもありません。

PDOは$sortbyリテラル文字列として解釈されます。これは、あなたが要求したことです。

SELECT ... WHERE image_active='y' 'literal string substituted here' ...

あなたは確かにそのクエリで構文エラーを生成しています。

やや紛らわしいのは、MySQLLIMIT句への引数のプレースホルダーを許可していることです。これは非常に便利ですが、他のRDBMSに精通している人にとっては驚くべきことです。

于 2012-10-03T19:27:10.553 に答える