質問: わかったようなわからないようなでいまいち整理がついていないので、理解が正しいか教えてください。 パラメータ付きSQLクエリの、変数指定の仕方についてです。 ・JDBC JDBCでは、どのRDB製品を使う場合も "?"(名前なしパラメータ)もしくは ":name"(名前付きパラメータ)で指定できる、これはあっていますよね。 ・Python ドライバとしてcx-oracleを使ってOracleを叩く場合、":name"(名前付きパラメータ)が使えます。"?"のような名前なしパラメータは指定できませんので、適当な名前の名前付きパラメータを使います。 ドライバとしてpsycopg2を使ってPostgresを叩く場合、"%s"(名前なしパラメータ)と "%(name)s"(名前付きパラメータ)が使えます。 さて、Pythonの場合だとRDB製品によってパラメータの埋め込み方が全然違っています。この違いを生んでいるのは ●OracleとPostgresの仕様の違い ●ドライバ同士の仕様の違い のどちらなのでしょう? パラメータ埋め込みの仕組みは各RDBが提供している通信インターフェースに依存していて、そのせいでPythonプログラミングレベルに違いが現れているのか、それとも単にそれぞれのドライバの設計者の気まぐれによって違いが出ているものなのか(つまりDB APIの規定がゆるゆるすぎるPythonが悪いのか!)。 後者なのかな? と思っていますが、そもそもパラメータ付きクエリをRDBに送り込むときはどういう形式の通信が行われているのかあたりをまったく把握していないので確証が持てていません。詳しい方ご教示いただけますでしょうか。
回答: 実際に DB が解釈できる構文は、DB によって決まります。 しかしそれでは面倒なのと、名前付きパラメータが使えない DB もあるので(MySQL とか)、ドライバのレベルでそれを拡張しています。 で...Python は DB ドライバのために DB API 2.0 という共通規格が定められています。これに沿っていれば、使う人は同じ使い方でいくつもの DB にアクセスできる(差異を吸収してくれる)わけです。 この規格上で、貴方自身もおっしゃられているようにパラメータの与え方が複数種類定義されているのです。各ドライバはこれらのうち最低どれか一つはサポートしていればよいので、ドライバによって使える構文が異なってしまっても構わないのです。 各ドライバは自身のサポートする構文に従って、 * 各 DB の仕様に合わせたパラメータ付きSQL に変換し * 各 DB の仕様に従ってパラメータを適切に再配置し * DB に SQL を発行する ので、DB に対しては DB 用の構文に変換した結果が流れます。 ※psycopg2 の名前付きパラメータでいえば、まずパラメータを出てきた順に $1, $2, ... に置き換えて(ただし同名であれば同じ $n にする)、それぞれに対して渡された値を埋め込むように呼び出し準備をする、といったような処理をする