生成SQL“IN”子句:如何安全地处理输入+空值列表?

2024-05-18 11:15:53 发布

您现在位置:Python中文网/ 问答频道 /正文

在Python代码中,我经常发现自己在做以下事情(使用DB-API):

yValues = pickInterestingValuesOfY()

sql = "..." # includes a clause stating that "y must be in yValues"

c.execute(sql, yValues)

最后,所执行的SQL可以简单到

^{pr2}$

问题是y(1,2,3)的一组可能值是在运行时确定的。在

我有两个顾虑:

  1. 在yValues为空的情况下生成有效的SQL(“where y in()”是无效SQL)
  2. 如果值来自不受信任的源,请注意sql注入

为了解决(2),我必须让DB-API在SQL语句中实际插入Yvalue。所以我得出了以下复杂的解决方案:

def inClause(columnName, values):

    if len(values):
         placeHolders = ','.join( ['%s'] * len(values) )
         sql = "%s IN (%s)" % (columnName, placeHolders)
    else: 
         sql = "FALSE"
    return "(%s)" % sql

# get a db-api cursor called c
c.execute("SELECT x FROM table1 WHERE %s;" % inClause('y', yValues), yValues)

这似乎正确地解决了上述两个问题。然而,我不能相信这个笨拙的解决方案就是它所需要的。在

您如何处理此类查询?我是不是错过了一个更优雅的方式?在

我不是在找ORM。在

(我使用的是MySQL,所以如果有一些神奇的MySQL非标准开关静默地接受'WHERE y IN()'为有效的,只需让我知道并注意(1)


Tags: inapiexecutedbsqllen解决方案where
3条回答

对于MySQL,可以执行以下操作:

SELECT x FROM table1 WHERE y IN (SELECT NULL FROM DUAL WHERE 0);

DUAL是一个虚拟表,它就是为此而诞生的。它适用于选择不需要表的数据。并且WHERE 0子句确保不会从子查询返回任何记录。在

简而言之,SELECT NULL FROM DUAL WHERE 0是空列表的完美替代。在

没有。没什么好办法的。对于以这种方式处理序列,DB-API没有任何规范。在

对于in子句,只需始终包含一个不在列表中的值(例如负整数)。在

相关问题 更多 >