Python で次のコードを使用します (MS-Access ベースの pyodbc を使用)。
cursor.execute("select a from tbl where b=? and c=?", (x, y))
問題ありませんが、メンテナンスのために、データベースに送信される完全かつ正確な SQL 文字列を知る必要があります。
それは可能ですか?
ドライバーによって異なります。以下に 2 つの例を示します。
import MySQLdb
mc = MySQLdb.connect()
r = mc.cursor()
r.execute('select %s, %s', ("foo", 2))
r._executed
"select 'foo', 2"
import psycopg2
pc = psycopg2.connect()
r = pc.cursor()
r.execute('select %s, %s', ('foo', 2))
r.query
"select E'foo', 2"
答えはノーだ。プロジェクトのホーム Google コード (および Google グループ) に質問を投稿しましたが、答えは次のとおりです。
l...@deller.id.au による issue 163 のコメント #1: cursor.mogrify はクエリ文字列を返します http://code.google.com/p/pyodbc/issues/detail?id=163
参考までに、レポーターが参照している「 mogrify」カーソル メソッドの pyscopg ドキュメントへのリンクを次に示します。
pyodbc はそのような SQL の変換を実行しません。パラメータ化された SQL を直接 ODBC ドライバーにそのまま渡します。関連する唯一の処理は、パラメータを Python オブジェクトから ODBC API でサポートされている C 型に変換することです。
SQL の一部の変換は、サーバーに送信される前に ODBC ドライバーで実行される場合があります (たとえば、Microsoft SQL Native Client はこれを行います) が、これらの変換は pyodbc から隠されています。
したがって、pyodbc で mogrify 機能を提供することは現実的ではないと思います。
デバッグ目的のために、単純に ? を置き換えるチェック関数を作成しました。クエリ値で...それは高度な技術ではありません:)しかし、それは機能します! :D
def check_sql_string(sql, values):
unique = "%PARAMETER%"
sql = sql.replace("?", unique)
for v in values: sql = sql.replace(unique, repr(v), 1)
return sql
query="""SELECT * FROM dbo.MA_ItemsMonthlyBalances
WHERE Item = ? AND Storage = ? AND FiscalYear = ? AND BalanceYear = ? AND Balance = ? AND BalanceMonth = ?"""
values = (1,2,"asdasd",12331, "aas)",1)
print(check_sql_string(query,values))
結果:
SELECT * FROM dbo.MA_ItemsMonthlyBalances WHERE Item = 1 AND Storage = 2 AND FiscalYear = 'asdasd' AND BalanceYear = 12331 AND Balance = 'aas') AND BalanceMonth = 1
これにより、ログに記録したり、好きなことをしたりできます。
rowcount = self.cur.execute(query,values).rowcount
logger.info(check_sql_string(query,values))
関数に例外キャッチを追加する必要がある場合。
使用するドライバーによっては、これが可能な場合と不可能な場合があります。一部のデータベースでは、?
user589983 の回答が示唆するように、パラメーター ( s) が単純に置き換えられます (ただし、ドライバーは、実行可能なステートメントを生成するために、文字列を引用したり、それらの文字列内の引用符をエスケープしたりする必要があります)。
他のドライバーは、データベースにステートメントをコンパイル (「準備」) するように要求し、次に、指定された値を使用して準備済みステートメントを実行するように要求します。このようにして、準備されたステートメントまたはパラメーター化されたステートメントを使用すると、SQL インジェクションを回避できます。ステートメントの実行時に、データベースは、実行したい SQL の一部と、使用されている値の一部を「認識」します。その声明。
PyODBCのドキュメントをざっと読んで判断すると、実際の SQL を実行できるようには見えませんが、間違っている可能性があります。
SQL 文字列を記述して実行します。
sql='''select a
from tbl
where b=?
and c=? '''
cursor.execute(sql, x, y)
print 'just executed:',(sql, x,y)
これで、SQL ステートメントでやりたいことを何でもできるようになりました。