看两段代码

1
2
sql = "UPDATE users SET {} = ? WHERE username = ?"
cursor.execute(sql.format(type_name), (datetime.now(), username))

这个可以正常运行

运行流程如下

1
sql = "UPDATE users SET {} = ? WHERE username = ?"

经过 format 方法处理后,那么更新语句变为:

1
UPDATE users SET type_name = ? WHERE username = ?

此处有两个参数占位符 ?,分别对应 datetime.now()username

而在执行更新操作时,您提供了两个参数:

1
cursor.execute(sql.format(type_name), (datetime.now(), username))

这里的 (datetime.now(), username) 是一个包含两个元素的元组,正好与 SQL 语句中的两个问号占位符相对应。因此,这次不会有参数数量不匹配的错误。

这里却会出现错误

1
2
sql = "SELECT {} FROM users WHERE username = ?"     # SQL查询模板,使用占位符代替字段名
cursor.execute(sql.format(type_name), (username))
1
2
An error occurred: Incorrect number of bindings supplied. The current 
statement uses 1, and there are 19 supplied.

出现错误 “Incorrect number of bindings supplied. The current statement uses 1, and there are 19 supplied.” 的原因在于执行 SQL 查询时提供的参数数量与 SQL 语句中的参数占位符数量不符。

在这个例子中,SQL 查询语句为:

1
SELECT {} FROM users WHERE username = ?

经过 format 方法处理后,那么查询语句变为:

1
SELECT type_name FROM users WHERE username = ?

此时,查询语句中有 1 个参数占位符 ?,因此在执行查询时应提供 1 个参数:

1
cursor.execute(sql.format(type_name), (username,))

但示例代码中,括号内的 username 没有用逗号分隔成元组,而是直接跟在了括号后面,这可能导致 Python 将其视为单个字符组成的列表,从而产生了 19 个字符,每个字符被视为一个参数传递给了数据库查询方法,与查询所需的参数数量不符,引发了此错误。

正确的做法是将 username 作为元组传递:

1
cursor.execute(select_sql.format(type_name), (username,))

在 Python 中,用一对圆括号 ( ) 包裹的一系列值构成了一个元组。即使元组中只有一个元素,也需要在该元素后面加上一个逗号 , 来明确表示这是一个元组,否则 Python 会将其视为一个单独的对象而非元组。

例如:

1
2
3
4
5
# 正确创建单元素元组
single_element_tuple = (1,) # 这是一个包含一个元素的元组

# 错误创建单元素“元组”(实际上是整数)
not_a_tuple = (1) # 这不是一个元组,只是一个简单的整数值

在 SQL 查询和更新语句的例子中,(datetime.now(), username) 是一个包含两个元素的元组,无论有多少元素,只要在最后的元素后添加逗号,Python 都会将其解释为元组,这正是执行 SQL 语句时需要的参数格式。