1. ホーム
  2. php

MySQL INステートメントのPDOバインディング値 [重複]について

2023-12-18 20:42:11

質問

私はPDOに関する問題で、かなり長い間悩まされてきたため、どうしても回答を得たいことがあります。

この例を見てください。

MySQL の IN 文で使用するために、PDO 文に ID の配列をバインドしています。

配列は次のようになります。 $values = array(1,2,3,4,5,6,7,8)。

データベースセーフな変数は次のようになります。 $products = implode(',' $values)となります。

では $products は、次に 文字列 という値を持つ。 '1,2,3,4,5,6,7,8'

この文は次のようになります。

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN (:products)

もちろん $products というステートメントにバインドされます。 :製品 .

しかし、このステートメントをコンパイルして値をバインドすると、実際には次のように表示されます。

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN ('1,2,3,4,5,6,7,8')

問題は、IN文にバインドするためにカンマ区切りの値として用意したのに、IN文の中のすべてを1つの文字列として実行していることです。

私が実際に必要としているのは

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN (1,2,3,4,5,6,7,8)

実際にこれを行うことができる唯一の方法は、バインドせずに文字列自体の中に値を配置することですが、私はこれを行うためのより簡単な方法があるはずだと確信しています。

どのように解決するのですか?

この質問で聞かれたのと同じことです。 IN()条件に配列を結合することは可能ですか?

そこでの回答は、可変サイズのリストに対して in 節にある可変サイズのリストでは、自分でクエリを作成する必要があるということでした。

しかし を使えば、引用符で囲んだカンマ区切りのリストを使うことができます。 find_in_set を使うこともできますが、大きなデータセットの場合、テーブルのすべての値を char 型にキャストしなければならないので、これはパフォーマンスにかなりの影響を及ぼします。

たとえば

select users.id
from users
join products
on products.user_id = users.id
where find_in_set(cast(products.id as char), :products)

あるいは、第三の選択肢として を使えば、カンマ区切りのリストを分割するユーザ定義の関数を作ることができます (cf. http://www.slickdev.com/2008/09/15/mysql-query-real-values-from-delimiter-separated-string-ids/ ). これはおそらく、3つのうちで最も良い方法でしょう。 in(...) 節に依存するクエリが多い場合は特に最適です。