17

假设我们有一个 SQL 语句,它只需要在对 DB 执行之前使用参数完成。例如:

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

更新。我从这个网页了解到,从 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 版本,否则它将仅匹配 ? 在 'values (' ', ' 或 ' = ' 之后。 '\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 回答