Python 将单引号添加到我的查询参数

Python adds single quote to my query parameters

提问人:Brodario 提问时间:10/2/2019 更新时间:10/2/2019 访问量:1782

问:

我正在尝试执行查询:

SELECT '23.34.67.0/22' CONCAT(DAY_31, 'hello') DAY_31 FROM Jule

使用 pymysql。我的代码是:

cursor.execute("SELECT %s CONCAT(%s, %s) %s FROM Jule", (p, 'DAY_' + _day, as_tmp, 'DAY_' + _day))

但是 python 添加了单引号并返回语法错误

“你的 SQL 语法有误;查看与您的MySQL服务器版本相对应的手册,了解在第1行的'('DAY_31', 'hello') 'DAY_31' FROM Jule'附近使用的正确语法”

DAY_31 是 Jule Schema 的一列

python mysql 引用 pymysql

评论

0赞 MikeMajara 10/2/2019
你检查过字符串转义吗?这个问题是否为您指明了正确的方向?我所说的字符串转义的意思是,似乎在您的字符串上进行了自动不需要的转义,并且可能有一种方法可以避免在 cursor.execute 函数中避免这种情况。
0赞 Brodario 10/2/2019
它返回“您的 SQL 语法有错误;查看与您的MySQL服务器版本相对应的手册,了解在第1行的'('\\'DAY_31\\'', '6762') '\\'DAY_31\\'' FROM Jule'附近使用的正确语法”
0赞 Brodario 10/2/2019
好的,缺少逗号 'cursor.execute(“SELECT %s, CONCAT(%s, %s) %s FROM Jule”, (p, 'DAY_' + day, as_tmp, 'DAY' + _day))
0赞 Booboo 10/2/2019
不应该是:,即你没有缺少逗号吗?SELECT '23.34.67.0/22', CONCAT(DAY_31, 'hello'), DAY_31 FROM Jule

答:

1赞 sjp 10/2/2019 #1

如果没记错的话,代替可能会解决问题。?%s

评论

0赞 Brodario 10/2/2019
感谢您的回答,但它返回“TypeError:在字符串格式化期间并非所有参数都转换”
-1赞 MikeMajara 10/2/2019 #2

实际上正在发生的事情与.这只是您在 python 中格式化字符串的方式。cursor.execute

我们首先应该注意 %s %d 可以特定于 SQL,并且这些也可以在 python 中用于字符串格式化。

因此,考虑到这一点,我认为您没有必要使用 %s 进行字符串格式设置(这无助于提高可读性)。由于您直接访问数据库,因此您可以直接在 python 中格式化字符串。cursor.execute

小检查一下发生了什么:

p = "23.34.67.0/22"
as_tmp = "hello"
_day = "3"
print("SELECT %s CONCAT(%s, %s) %s FROM Jule", (p, 'DAY_' + _day, as_tmp, 'DAY_' + _day))
# output
# SELECT %s CONCAT(%s, %s) %s FROM Jule ('23.34.67.0/22', 'DAY_3', 'hello', 'DAY_3')
# ^^^^ so this is what is being sent in cursor.execute (with all the quotes and so on)

如果你用 f 字符串格式化,你会增加可读性,你应该摆脱引号的问题

print(f"SELECT '{p}' CONCAT(DAY_{_day}, '{as_tmp}') DAY_{_day} FROM Jule")
# output
# SELECT '23.34.67.0/22' CONCAT(DAY_3, 'hello') DAY_3 FROM Jule

因此,解决方案可能是:

cursor.execute(f"SELECT '{p}' CONCAT(DAY_{_day}, '{as_tmp}') DAY_{_day} FROM Jule")

评论

0赞 Brodario 10/2/2019
感谢您的回答,但问题是缺少逗号。无论如何,我会记住你的答案
1赞 Rob Streeting 10/2/2019
如果可能来自应用程序外部,则此答案使应用程序容易发生 SQL 注入。原始方法适用于字符串数据值,但无法避免像您建议的那样在字段名称中进行拼接。as_tmp
0赞 Rob Streeting 10/2/2019 #3

你最终得到引号的原因是,在你作为参数传入的值周围添加这些引号。这完全适用于您的第二个参数,因为如果按原样将值“hello”插入到查询中,您最终会得到如下查询:cursor.execute

 SELECT '23.34.67.0/22' CONCAT(DAY_31, hello) DAY_31 FROM Jule

并且您会错误地告诉您MySQL无法识别应该引用的内容。hello

显然,这不适用于要传入字段名称或查询中不是基元字符串值的任何其他部分的情况。在这些情况下,您需要在执行查询之前将它们拼接到字符串中。一种方法是使用 f 字符串,但也有其他选择。这是使用 f 字符串拼接的字段名称的行:cursor.execute

cursor.execute(f"SELECT %s, CONCAT({'DAY_'+_day}, %s) {'DAY_'+_day} FROM Jule", (p, as_tmp))

请注意,我也已从参数列表中删除了 。'DAY_'+_day

重要提示:

虽然这应该像这样工作(尽管我认为您还需要一个额外的逗号,我在上面的示例中添加了逗号),但非常重要的一点是,如果有一个来自应用程序外部的值(例如,由用户在表单字段中传入),请确保它在将其拼接到查询之前完全采用您想要的格式。检查字符串值是否为整数可能是执行此操作的一种方法。它之所以重要,是因为如果没有它,您的应用程序可能容易发生 SQL 注入,这可能会允许用户在您的数据库上运行任意 SQL。如果 的值仅由应用程序计算,则无需担心此问题。SELECT '23.34.67.0/22'dayday