Python(MS-Accessベースのpyodbcを使用))で次のコードを使用します。
cursor.execute("select a from tbl where b=? and c=?", (x, y))
Okですが、メンテナンスのために、データベースに送信される完全かつ正確なSQL文字列を知る必要があります。
それは可能ですか?
答えはいいえだ。私の質問はプロジェクトのホームGoogleコード(およびGoogleグループ)に投稿します。答えは次のとおりです。
L ... @ deller.id.auによるissue 163のコメント#1:cursor.mogrify return query string http://code.google.com/p/pyodbc/issues/detail?id=16
ここで参照できるのは、レポーターが参照している「mogrify」カーソルメソッドのpyscopgドキュメントへのリンクです。 http://initd.org/psycopg/docs/cursor.html#cursor.mogrify
pyodbcはこのようなSQLの変換を実行しません。パラメーター化されたSQLをそのままODBCドライバーにそのまま渡します。関係する唯一の処理はPython ODBC API。
SQLの一部の変換は、サーバーに送信される前にODBCドライバーで実行される場合があります(Microsoft SQL Native Clientはこれを行います)が、これらの変換はpyodbcから隠されます。
したがって、pyodbcでmogrify関数を提供することは現実的ではないと思います。
ドライバーによって異なります。以下に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"
_print cursor._last_executed
_を使用して、最後に実行されたクエリを取得できます。
this を読んで、print cursor.mogrify(query,list)
を使用して、実行前または実行後に完全なクエリを表示することもできます。
デバッグ目的のために、私は単に置換するチェック関数を作成しましたか?クエリ値で...それは高度な技術ではありません:)が、それは動作します! :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))
必要に応じて、関数にキャッチする例外を追加します。
使用するドライバーに応じて、これは可能または不可能です。一部のデータベースでは、パラメーター(?
s)は、user589983の答えが示すように単純に置き換えられます(ただし、ドライバーは、実行可能なステートメントを生成するために、文字列を引用したり、それらの文字列内の引用符をエスケープしたりする必要があります)。
他のドライバーは、データベースにステートメントをコンパイル(「準備」)するように要求し、指定された値を使用して準備済みステートメントを実行するように要求します。このようにして、準備済みまたはパラメーター化されたステートメントを使用すると、SQLインジェクションを回避できます-ステートメントの実行時に、データベースは、実行するSQLの一部と、使用する値の一部を「認識」しますその声明。
PyODBCドキュメンテーション をざっと読んで判断すると、実際のSQLを実行することは可能であるようには見えませんが、私は間違っているかもしれません。
後でcursor._last_executedをチェックしますが、実行するたびに変更せずにリアルタイムで印刷したい場合は、このモンキーパッチを試してください。
def log_queries(cur):
def _query(q):
print q # could also use logging
return cur._do_query(q)
cur._query = _query
conn = MySQLdb.connect( read_default_file='~/.my.cnf' )
cur = conn.cursor()
log_queries(cur)
cur.execute('SELECT %s, %s, %s', ('hello','there','world'))
MySQLdbに非常に依存しています(それ以降のバージョンでは機能しなくなる可能性があります)。現在、cur._queryは単にcalls._do_queryを呼び出し、その結果を返すため、機能します。