首页 > 解决方案 > 在 Python 中参数化 DELETE SQL 语句时遇到问题

问题描述

我正在编写一个 Python3 脚本来处理 MySQL 数据库。使用 mysql.connector 功能。

我正在尝试编写 DELETE 命令。我可以让它与静态字符串一起使用,但我无法让它与参数化语句一起使用。

这个有效:

sql = "DELETE FROM mytable where report_dt < '" + str(report_date) + "'"
try:
    mycursor.execute(sql)
    mydb.commit()

这个失败了:

sql = "DELETE FROM mytable where report_dt < '%s'"
try:
    mycursor.execute(sql, report_date)
    mydb.commit()

report_date 变量来自 datetime.datetime.now() ,格式如下:

str(report_date) 返回:'2020-06-09 10:59:11'</p>

没有错误消息......它实际上并没有删除它应该删除的行。

标签: mysqlsqlpython-3.xdatetimedelete-row

解决方案


这些中的任何一个都应该这样做。

sql = "DELETE FROM mytable WHERE report_dt < %(date)s;"
try:
    mycursor.execute(sql, {'date': str(report_date)})
    mydb.commit()
except:
    print(f"Error deleting report from {report_date}.")

或者

sql = "DELETE FROM mytable WHERE report_dt < %s;"
try:
    mycursor.execute(sql, [str(report_date)])
    mydb.commit()
except:
    print(f"Error deleting report from {report_date}.")

Python PEP 249涵盖了数据库库为了在 Python 中保持一致性而应遵循的 API。

方法下execute

参数可以作为序列或映射提供,并将绑定到操作中的变量。

通常,我尝试始终使用映射(例如dict),以便对 SQL 中的内容有一些易于理解的清晰度。尤其是当我需要在多个地方重复相同的内容时。

list我可以为只有一个或两个参数的简短查询做一个序列(例如)。


从评论中,为了澄清尝试参数化的问题存在两个问题。首先,Cursor.execute() 的“参数”参数需要是序列或映射类型。其次,查询的参数化操作将处理任何需要的引用,因此参数标记周围的单引号(即'%s'%s)会导致难以理解的错误消息。

没有引用是因为参数化使查询安全,所以写在 SQL 语句本身中的任何其他内容都不需要做任何事情。不幸的是,像“SQL 语法错误”这样的简单消息并不能说明这一点。我在文档中能找到的最好的东西是Type Objects and Constructors。pyscopg2 文档确实有一个关于 quoting 的部分


推荐阅读