我正在使用 Python
以及 PyMySQL
. 我想从mysql数据库中根据项目的ID获取一些项目:
items_ids = tuple([3, 2])
sql = f"SELECT * FROM items WHERE item_id IN {items_ids};"
我正在使用格式化的字符串文本( f" "
, https://docs.python.org/3/whatsnew/3.6.html#whatsnew36-pep498)来计算sql语句中的元组。
但是,我想按元组指定的顺序取回项,因此首先使用 item_id = 3
然后是 item_id = 2
. 要做到这一点,我必须使用 ORDER BY FIELD
子句(另请参见:按SQLIn()子句中值的顺序排序)。
但如果我写下这样的话:
items_ids = tuple([3, 2])
sql = f"SELECT * FROM items WHERE item_id IN {items_ids} ORDER BY FIELD{(item_id,) + items_ids};"
那么 item_id
在 ORDER BY FIELD
子句被视为未声明的python变量
如果我写下这样的话:
items_ids = tuple([3, 2])
sql = f"SELECT * FROM items WHERE item_id IN {items_ids} ORDER BY FIELD{('item_id',) + items_ids};"
那么 item_id
在 ORDER BY FIELD
子句被视为字符串而不是sql变量,在本例中 ORDER BY FIELD
什么都不做。
如何计算元组 (item_id,) + items_ids
在sql语句中 item_id
作为 ORDER BY FIELD
条款?
显然,我可以在项目从数据库返回后根据 items_ids
我不太在意mysql,但我只是想知道如何做到这一点。
3条答案
按热度按时间vuktfyat1#
解决此单元素元组问题的另一种更简单的方法是检查元素的长度,方法是将其保留在列表中并将其保留为列表,而不是将其作为元组传递给cursor param:
如:
通过使用上述代码,您将无法在sql中获得(item\u id,)此错误:)
vlf7wbxs2#
解决方案
.format()
具体如下:一个相当棘手的解决方案
f-strings
具体如下:但作为
@IIija
提到,我可能会得到一个SQL injection
因为IN {item_ids}
不能容纳一个元素元组。另外,使用
f-strings
在字符串中解包元组可能比使用.format()
正如其他人之前所提到的(在python3.6中格式化的字符串文本带有元组),因为您不能使用*
解包f-string
. 但是,也许您可以为此提出一个解决方案(使用迭代器?)来产生这个结果尽管我现在还没有解决这个问题的办法。如果您有这种想法,欢迎您发布解决方案。
8zzbczxx3#
请不要使用f字符串或任何字符串格式将值传递给sql查询。这就是sql注入之路。现在您可能会想:“这是一个整数元组,会发生什么坏事?”首先,一个元素python元组的字符串表示形式不是有效的sql。其次,有人可能会用用户可控制的数据(而不是int的元组)来仿效这个例子(因此,让这些坏例子在线会延续这个习惯)。另外,你不得不求助于你的“狡猾”解决方案的原因是使用了错误的工具。
向sql查询传递值的正确方法是使用占位符。对于pymysql,占位符有点混乱
%s
. 不要把它和手工格式化混在一起。如果必须向查询传递数量可变的值,则必须采用某种字符串生成方法,但生成的是占位符,而不是值: