mysql - 在 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>
没有错误消息......它实际上并没有删除它应该删除的行。
解决方案
这些中的任何一个都应该这样做。
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 的部分。
推荐阅读
- javascript - 在 HTML 中传递 url 中的变量
- android - Android Context的扩展功能在哪里?
- wordpress - 如何获取元名称
- c# - 线程安全的任务队列等待
- python - QCalendarWidget 使用 pyqt5 点击年份
- spring - Spring Batch:在内存数据库中用于 Spring Batch 元数据表
- javascript - 如何在没有 xhr、fetch 甚至 websockets 的情况下发送 api 请求?
- python - Python正则表达式'findall'没有返回所有表达式
- sql - 如何在sql中获取列值作为表列
- hyperledger-fabric - Hyperledger Fabric 提交交易失败:错误:背书失败