web-dev-qa-db-ja.com

プリペアドステートメントを使用したMySQLのLIMITキーワード

SELECT id, content, date
FROM comment
WHERE post = ?
ORDER BY date DESC
LIMIT ?, ?

PDO(Apache2.2.21を含むMAMP2.0.5を使用していますPHP最大5.3.6、およびMySQL 5.5.9)プリペアドステートメントでは、これは機能しません。でクエリを変更します

LIMIT 0, 10

できます。

MySQLのバグで、これは以前のバージョンのバグであることがわかりましたが、これがまだ修正されるかどうかはわかりません。

それでも問題が解決しない場合は、別の方法で行の範囲を選択する方法がありますか?

コード:

$comments = $db->prepare($query); 
/* where $db is the PDO object */ 
$comments->execute(array($post, $min, $max)); 
22
genesisxyz

ここに問題があります:

$comments = $db->prepare($query); 
/* where $db is the PDO object */ 
$comments->execute(array($post, $min, $max));

PDOStatement :: execute() のマニュアルページには次のように書かれています(私の強調):

パラメータ

input_parameters実行中のSQLステートメントにバインドされたパラメーターと同じ数の要素を持つ値の配列。 すべての値はPDO :: PARAM_STRとして扱われます。

したがって、パラメータは文字列として挿入されるため、最終的なSQLコードは次のようになります。

LIMIT '0', '10'

これは、MySQLが数値にキャストせず、解析エラーをトリガーする特定のケースです。

mysql> SELECT 1 LIMIT 0, 10;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)

mysql> SELECT 1 LIMIT '0', '10';
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''0', '10'' at line 1

docs 言わなければならない:

LIMIT句を使用して、SELECTステートメントによって返される行数を制限できます。 LIMITは、次の例外を除いて、1つまたは2つの数値引数を取ります。これらは両方とも非負の整数定数でなければなりません。

  • プリペアドステートメント内で、LIMITパラメーターは?を使用して指定できます。プレースホルダーマーカー。

  • ストアドプログラム内では、整数値のルーチンパラメータまたはローカル変数を使用してLIMITパラメータを指定できます。

選択肢は次のとおりです。

  • タイプを設定できるように、パラメーターを1つずつバインドします。

    $comments->bindParam(1, $post, PDO::PARAM_STR);
    $comments->bindParam(2, $min, PDO::PARAM_INT);
    $comments->bindParam(3, $min, PDO::PARAM_INT);
    
  • これらの値をパラメーターとして渡さないでください。

    $query = sprintf('SELECT id, content, date
        FROM comment
        WHERE post = ?
        ORDER BY date DESC
        LIMIT %d, %d', $min, $max);
    
  • エミュレートされた準備を無効にします(MySQLドライバーには、数値引数を引用するバグ/機能があります):

    $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
    
44
$dbh->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );

この問題を解決します。

4