将字符串变量传递给 MySQL,作为元组失败

Passing string variable to MySQL, fails as tuple

使用新购买的 RaspberryPi,我对 Python/MySQL 还很陌生,所以请原谅我提出的天真问题。 我看过许多关于此的问答,但我似乎无法理解 'why' 这是失败的。我得到错误:"must be string or read-only buffer, not tuple"。如果我用 TYPE 测试它,我的变量显示为一个字符串,所以现在我迷路了。

import MySQLdb
import time
db = MySQLdb.connect(host="localhost", user="user",passwd="easypwd", db="imagepi")
cursor = db.cursor()
current_time = time.strftime("%H:%M:%S")
current_date = time.strftime("%Y-%m-%d")
filename = (current_time+'.jpg')
sql = ("""INSERT INTO imagelocator(batch, date, time, filename) VALUES
('1001', current_date, current_time, %s)""", filename)
cursor.execute(sql)
db.commit()
db.close()

非常感谢你在正确的方向上给了我一点推动。

sql 变量是一个元组。其中一半是您的 SQL 语句,另一半是您语句中 %s 参数的标记值。但是,简单地将元组传递给参数并不会将其分解并将元组中的每个元素用作单独的参数。为此,您必须使用星号:function_to_call(*tuple_args) ...但我认为您也会遇到问题,因为数据库游标需要 statement 参数的字符串,并且parameters 参数的序列。 parameters 参数必须是一个序列(元组、列表、集合等)即使只有一个值

TL;DR - 你需要做更多像这样的事情:

sql = "INSERT INTO table_name (a_column, b_column) VALUES ('asdf', %s)"
args = (filename,)
cursor.execute(sql, args)

... 或者,如果你真的想变得狡猾并为所有内容使用元组:

sql = ("INSERT INTO table_name (a_column, b_column) VALUES ('asdf', %s)", (filename,))
cursor.execute(*sql)

编辑:我想我没有澄清...虽然用括号括起字符串不会创建元组,但添加逗号 。所以,(string_var) 不是元组,而 (string_var,) 是。希望这消除了对上述代码如何运行的任何混淆。

另外,这里有一些关于星号的文档;无聊的官方文档和更容易理解的博客 post: