69

Python で次のコードを使用します (MS-Access ベースの pyodbc を使用)。

cursor.execute("select a from tbl where b=? and c=?", (x, y))

問題ありませんが、メンテナンスのために、データベースに送信される完全かつ正確な SQL 文字列を知る必要があります。
それは可能ですか?

4

9 に答える 9

68

ドライバーによって異なります。以下に 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"
于 2011-03-10T22:52:11.267 に答える
12

答えはノーだ。プロジェクトのホーム 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 機能を提供することは現実的ではないと思います。

于 2011-03-16T08:31:12.963 に答える
3

デバッグ目的のために、単純に ? を置き換えるチェック関数を作成しました。クエリ値で...それは高度な技術ではありません:)しかし、それは機能します! :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 St​​orage = 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))

関数に例外キャッチを追加する必要がある場合。

于 2014-02-27T07:14:05.620 に答える
2

使用するドライバーによっては、これが可能な場合と不可能な場合があります。一部のデータベースでは、?user589983 の回答が示唆するように、パラメーター ( s) が単純に置き換えられます (ただし、ドライバーは、実行可能なステートメントを生成するために、文字列を引用したり、それらの文字列内の引用符をエスケープしたりする必要があります)。

他のドライバーは、データベースにステートメントをコンパイル (「準備」) するように要求し、次に、指定された値を使用して準備済みステートメントを実行するように要求します。このようにして、準備されたステートメントまたはパラメーター化されたステートメントを使用すると、SQL インジェクションを回避できます。ステートメントの実行時に、データベースは、実行したい SQL の一部と、使用されている値の一部を「認識」します。その声明。

PyODBCのドキュメントをざっと読んで判断すると、実際の SQL を実行できるようには見えませんが、間違っている可能性があります。

于 2011-03-10T22:44:00.167 に答える
-4

SQL 文字列を記述して実行します。

sql='''select a 
       from tbl 
       where b=? 
       and c=? '''

cursor.execute(sql, x, y)
print 'just executed:',(sql, x,y)

これで、SQL ステートメントでやりたいことを何でもできるようになりました。

于 2011-03-10T22:06:15.817 に答える