【问题标题】:Pass a python list to an SQL Query将 python 列表传递给 SQL 查询
【发布时间】:2015-07-03 12:31:43
【问题描述】:
res = db.execute("""
SELECT CAST ((SUM(r.SalesVolume)/1000.0) AS decimal(6,1))
FROM RawData r
INNER JOIN Product p
ON r.ProductId = p.ProductId 
INNER JOIN Calendar c
ON r.DayId = c.DayId
WHERE c.WeekCodeInYear BETWEEN 1 AND 12
AND 
c.YearId = 2014
AND p.Distributor IN (%s)
GROUP BY c.WeekCodeInYear """ % _studios)

_studios 是一个 Python 列表,是 JSON 对象的一部分。可以读作:

["WARNER","TF1","GAUMONT","PATHE","STUDIOCANAL","FRANCETV","M6SND"]

但是,当我尝试执行此操作时,出现错误:

ProgrammingError: (ProgrammingError) (207, "Invalid column name 'u'WARNER', u'TF1', 
u'GAUMONT', u'PATHE', u'STUDIOCANAL', u'FRANCETV', u'M6SND''.DB-Lib error message 20018, 
severity 16:\nGeneral SQL Server error: Check messages from the SQL

但是,数据库具有指定的所有列。我想这与格式有关。不过不确定。

在命令提示符下打印的查询可以看成:

SELECT CAST ((SUM(r.SalesVolume)/1000.0) AS decimal(6,1))
FROM RawData r
INNER JOIN Product p
ON r.ProductId = p.ProductId
INNER JOIN Calendar c
ON r.DayId = c.DayId
WHERE c.WeekCodeInYear BETWEEN 1 AND 12
AND
c.YearId = 2014
AND p.Distributor IN ([u'WARNER', u'TF1', u'GAUMONT', u'PATHE', u'STUDIOCANAL',
u'FRANCETV', u'M6SND'])
GROUP BY c.WeekCodeInYear

我注意到p.distributor 行中的[ ] 可能是问题?

【问题讨论】:

  • 这很容易受到注入攻击,即使在您将列表连接成逗号分隔字符串的“固定”版本中也是如此。使用您的 SQL API 提供的任何参数化查询实现。

标签: python sql json


【解决方案1】:

确实是这个问题。您正在使用列表的__repr__ 版本。相反,使用str.join 函数将其变为可用字符串,并结合列表推导来引用字符串:

"""SELECT CAST ((SUM(r.SalesVolume)/1000.0) AS decimal(6,1))
FROM RawData r
INNER JOIN Product p
ON r.ProductId = p.ProductId
INNER JOIN Calendar c
ON r.DayId = c.DayId
WHERE c.WeekCodeInYear BETWEEN 1 AND 12
AND
c.YearId = 2014
AND p.Distributor IN ({})
GROUP BY c.WeekCodeInYear """.format(', '.join(["'" + studio + "'" for studio in _studios]))

但是,如果有更多参数的更复杂查询,这将变得非常难以维护和阅读。上面的解决方案的格式语句已经很难理解了,只会变得更糟。

正如 roippi 所指出的,它也容易受到 SQL 注入的影响。他们对使用参数化查询的建议也是正确的。

【讨论】:

  • 这会将字符串转换为("WARNER", "TF1", "GAUMONT", "PATHE", "STUDIOCANAL", "FRANCTV", "M6SND")。所以基本上双引号不起作用吗?我需要的是('WARNER', 'TF1', 'GAUMONT', 'PATHE', 'STUDIOCANAL', 'FRANCTV', 'M6SND')
  • 哎呀,忽略了你的要求,但我现在已经修好了。 :)
  • 现在这个解决方案根本不读取字符串 :( 上一个读取字符串但是"
  • 适用于我的 Python 2.7 和 3.4,你有什么问题?
  • 现在工作!可能是我的一些语法问题。但是是的,我还有大约 5 个参数要添加。在那种情况下,这个解决方案将变得不可行?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
相关资源
最近更新 更多