1. ホーム
  2. php

[解決済み] PDO のプリペアドステートメントから生の SQL クエリ文字列を取得する

2022-05-31 06:06:17

質問

PDOStatement::execute() をプリペアドステートメント上で呼び出したとき、実行された生の SQL 文字列を取得する方法はありますか。デバッグのために、これは非常に有用でしょう。

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

パラメータ値を補間した最終的な SQL クエリが必要だということでしょう。 これがデバッグのために有用であることは理解できますが、プリペアド ステートメントが動作する方法ではありません。 パラメータはクライアント側でプリペアド ステートメントと結合されないので、PDO はパラメータと結合されたクエリ文字列にアクセスすることはできないはずです。

SQL 文は prepare() のときにデータベースサーバーに送信され、 パラメータは execute() のときに別々に送信されます。 MySQL の一般的なクエリ ログには、execute() を実行した後に補間された値を含む最終的な SQL が表示されます。 以下は、私の一般的なクエリログからの抜粋です。 PDO からではなく、mysql CLI からクエリを実行しましたが、原理は同じです。

081016 16:51:28 2 Query       prepare s1 from 'select * from foo where i = ?'
                2 Prepare     [2] select * from foo where i = ?
081016 16:51:39 2 Query       set @a =1
081016 16:51:47 2 Query       execute s1 using @a
                2 Execute     [2] select * from foo where i = 1

PDO 属性 PDO::ATTR_EMULATE_PREPARES を設定すれば、望みのものを得ることもできます。 このモードでは、PDO はパラメータを SQL クエリに補間し、 execute() したときにクエリ全体を送信します。 これは真のプリペアドクエリではありません。 execute()の前にSQL文字列に変数を補間することで、プリペアドクエリの利点を回避することになります。


afilinaのコメントを再掲します。

いいえ、テキスト形式の SQL クエリは ではなく は実行時にパラメータと組み合わされます。ですから、PDO が表示するものは何もありません。

内部的には、PDO::ATTR_EMULATE_PREPARES を使用すると、PDO は準備と実行を行う前に SQL クエリのコピーを作成し、パラメータ値をそこに補間します。しかし、PDO はこの修正された SQL クエリを公開しません。

PDOStatement オブジェクトには $queryString というプロパティがありますが、これは PDOStatement のコンストラクタにのみ設定され、クエリがパラメータで書き直されたときに更新されるわけではありません。

PDOに対して、書き換えられたクエリを公開するように要求するのは、妥当な機能要求でしょう。しかし、それでも PDO::ATTR_EMULATE_PREPARES を使用しない限り、quot; complete" クエリを得ることはできません。

この場合、パラメータプレースホルダを含むプリペアドクエリでさえ、サーバ上で書き直され、パラメータ値がクエリ文字列に埋め戻されるからです。しかし、これはロギング中にのみ行われ、クエリ実行中には行われません。