创建元组时如何在末尾避免逗号? [复制]

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,))

【讨论】:

以上是关于创建元组时如何在末尾避免逗号? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为什么Python在列表和元组的末尾允许使用逗号?

[Python]-4-元组列表与字典

关于python的元组操作

python3 元组

在递归二叉树函数中返回元组时遇到问题

将每个元素视为元组时,在 PySpark 中加入 2 个 RDD