17

DBに対して実行される前に、パラメーターを使用して完了する必要があるSQLステートメントがあるとします。例えば:

sql = '''
      SELECT  id, price, date_out
      FROM sold_items
      WHERE date_out BETWEEN ? AND ?
      '''

database_cursor.execute(sql, (start_date, end_date))

解析および実行される文字列を取得するにはどうすればよいですか?次のようになります。

SELECT  id, price, date_out
FROM sold_items
WHERE date_out BETWEEN 2010-12-05 AND 2011-12-01

この単純なケースではそれほど重要ではありませんが、他のSQLステートメントははるかに複雑です。デバッグの目的で、自分でsqliteマネージャーで実行し、結果を確認したいと思います。

前もって感謝します

4

4 に答える 4

30

アップデート。このWebページから、Python 3.3以降、実行されたSQLの印刷をトリガーできることを学びました。

connection.set_trace_callback(print)

サイレント処理に戻したい場合は、

connection.set_trace_callback(None)

の代わりに別の関数を使用できますprint

于 2018-03-04T21:37:37.160 に答える
8

SQLiteは、実際にパラメータをSQLクエリ文字列自体に置き換えることはありません。パラメータの値は、コマンドの実行時に直接読み取られます。(これらの値をフォーマットして、同じ値に再度解析するだけでは、無駄なオーバーヘッドになります。)

ただし、SQLでパラメーターがどのように記述されるかを知りたい場合は、quote関数;を使用できます。このようなもの:

import re
def log_and_execute(cursor, sql, *args):
    s = sql
    if len(args) > 0:
        # generates SELECT quote(?), quote(?), ...
        cursor.execute("SELECT " + ", ".join(["quote(?)" for i in args]), args)
        quoted_values = cursor.fetchone()
        for quoted_value in quoted_values:
            s = s.replace('?', quoted_value, 1)
            #s = re.sub(r'(values \(|, | = )\?', r'\g<1>' + quoted_value, s, 1)
    print "SQL command: " + s
    cursor.execute(sql, args)

(このコードは?、パラメーターではない場合、つまりリテラル文字列内にある場合は失敗します。re.subバージョンを使用しない限り、値(''、'または'='の後の?のみに一致します。 '\ g <1>'はテキストを?の前に戻し、'\ g <>'を使用すると、数字で始まるquoted_valuesとの衝突を回避できます。)

于 2012-11-30T14:42:35.123 に答える
0

疑問符に引数を入力するだけの関数を作成しました。

誰もが位置引数を使用する方向にあなたを送るのは奇妙ですが、クエリ全体をログに記録したり、プレビューしたり、チェックしたりする必要性については誰も考えていませんでした。

とにかく、以下のコードは

  • '?'がないこと 位置引数トークンとして機能しないクエリ内のトークン。それが常に当てはまるかどうかはわかりません。
  • 引数の値は引用符で囲まれます。これは、たとえばテーブル名に引数を使用する場合には当てはまりません。ただし、このユースケースはありそうにありません。
    def compile_query(query, *args):
        # test for mismatch in number of '?' tokens and given arguments
        number_of_question_marks = query.count('?')
        number_of_arguments = len(args)

        # When no args are given, an empty tuple is passed
        if len(args) == 1 and (not args[0]):
            number_of_arguments = 0
        
        if number_of_arguments != number_of_question_marks:
            return f"Incorrect number of bindings supplied. The current statement uses {number_of_question_marks}, and there are {number_of_arguments} supplied."

        # compile query
        for a in args:
            query = query.replace('?', "'"+str(a)+"'", 1)

        return query

推奨される使用法

query = "INSERT INTO users (name, password) VALUES (?, ?)"

# sensitive query, we need to log this for security
query_string = compile_query(query, username, password_hash)
fancy_log_function(query_string)

# execute
cursor.execute(query, username, password_hash)
于 2020-07-31T20:33:06.597 に答える
-4

文字列のフォーマットはどうですか?

sql = """
  SELECT  id, price, date_out
  FROM sold_items
  WHERE date_out BETWEEN {0} AND {1} """.format(start_date, end_date)
  """
database_cursor.execute(sql)
于 2012-11-30T15:52:30.507 に答える