创建元组时如何在末尾避免逗号? [复制]
Posted
技术标签:
【中文标题】创建元组时如何在末尾避免逗号? [复制]【英文标题】:How to avoid comma at the end when creating a tuple? [duplicate] 【发布时间】:2017-06-14 08:52:14 【问题描述】:我的 python 代码中有以下查询:
query = """SELECT id
FROM dings_archive
WHERE doorbot_id IN doorbot_ids;
"""
query = query.format(doorbot_ids=tuple(doorbot_ids))
doorbot_ids
的类型为 List[int]
,当我的数组仅包含 1 个元素时我遇到了问题,因为在 query.format
之后我有以下查询:
SELECT id
FROM dings_archive
WHERE doorbot_id IN (123,);
如您所见,我有一个错误,因为末尾有逗号 ,
。如何解决这个问题?
【问题讨论】:
也许你应该做query.format(doorbot_ids=", ".join(doorbot_ids))
(在query
中手动添加括号)
因为 door_bots 是一个元组
@RompePC 这是个坏主意,因为人们可能会注入 SQL 代码并造成严重破坏。
从列表或元组中取出 repr 并做一些正则表达式?
@Nils Werner 在这两种情况下最终的 SQL 都是相同的(除了最后的逗号),(123)
,我不明白为什么它会造成严重破坏。如果它在一个失败,它在另一个失败。另一种情况是他/她在这样做时正在逃避价值。
【参考方案1】:
为防止 SQL 注入,您永远不应使用将元组自动转换为字符串(您当前正在执行的操作),或在将值列表传递给驱动程序之前手动加入值列表。
您目前正在利用元组转换为字符串产生合理结果的事实:
str((1, 2))
# '(1, 2)'
但正如您所注意到的,单元素元组会产生语法错误:
str((1, ))
# '(1,)'
有些人建议手动连接列表:
','.join((1, 2))
# '1,2'
这也适用于单元素元组:
','.join((1,))
# '1'
然而,这为 SQL 注入打开了大门,因为逗号实际上是 mysql 的控制语句,而不仅仅是一个值。因此,如果有人能够在您的列表中偷偷控制语句,他们可以注入代码:
','.join((1,'1) OR 1=1 --'))
# '1,1) OR 1=1 --'
为了防止此类攻击,您应该准备一个查询,其中的占位符与您的 id 列表中的元素一样多:
doorbot_ids = [1, 2]
query = "SELECT id FROM dings_archive WHERE doorbot_id IN ();".format(','.join(['%s'] * len(doorbot_ids)))
这将返回一个新查询,其中包含所需数量的占位符:
'SELECT id FROM dings_archive WHERE doorbot_id IN (%s,%s);'
然后每个占位符填充一个值:
query = cursor.execute(query, doorbot_ids)
【讨论】:
这个query = query.format(doorbot_ids ='(%s)' % ', '.join(map(repr, doorbot_ids)))
怎么样?你的算法的时间复杂度有什么区别吗?
这个query = query.format(doorbot_ids)
也没有用值填充占位符。执行后我得到了SELECT id FROM dings_archive WHERE doorbot_id IN (%s);
抱歉,我打错了。你显然应该使用cursor.execute()
。
我的回答中回答了第一个问题。不要这样做。
这对于一个元素列表将失败,因为它会在末尾添加一个逗号。【参考方案2】:
好的,在这里跳出框框思考:如果您必须在 WHERE IN
子句中使用元组,您始终可以测试元组的长度。如果元组长度 == 1,则使用 list(tuple_object)
将其转换为列表,将列表附加到索引 0 处的值,然后将其转换回元组!
脚步:
1. the_single_value_tuple=('Salim',)
2. a_list= list(the_single_value_tuple)
3. return tuple(a_list.append(a_list[0])
【讨论】:
【参考方案3】:列表不转元组,直接使用:
query = """SELECT id
FROM dings_archive
WHERE doorbot_id = any(%s);
"""
...
cursor.mogrify(query, (doorbot_ids,))
【讨论】:
以上是关于创建元组时如何在末尾避免逗号? [复制]的主要内容,如果未能解决你的问题,请参考以下文章