2016-08-18 28 views
0

我的意思是这样的:传递许多参数的Django光标的一个占位符(placeholer在IN)

from django.db import connection 
cursor=connection.cursor() 
cursor.execute('SELECT * FROM mytable where id IN (%s)', [params]) 

参数不能只是迭代 - 这是行不通的。 由于数据库处理程序存在转义值,因此无法使用CSV格式。

如何在IN内使用占位符?


通过CSV是错的,我的意思是,对于params=['1','2','3','4','5']

c.execute('select * from mytable where id in (%s)', [','.join(params)]) 

会产生:

select * from mytable where id in ('1,2,3,4,5') 

但正确的SQL是:

select * from mytable where id in (1,2,3,4,5) 

,它似乎很难实现占位符。

+1

不确定你的意思是'它不能以CSV格式'。 IN期望一个值列表,必须用逗号分隔。如果你的'params'是一个列表,你应该做一些像'','join(params)'。这会将一个像[1,2,3]这样的列表转换成一个像1,2,3的字符串。 –

+0

在SQl中谨慎使用'%s'作为占位符,它可能让您容易受到SQL注入攻击https://xkcd.com/327/ –

+0

@Chris_Rands:它不是关于虚拟''%s“%params'。 –

回答

0

不能使用IN对于这一点,因为事实上,在预计整数序列,但ORM转换列表到ARRAY,如果你使用join,你最终会得到一个字符串。

解决方案是使用等效的ANY。该格式稍有不同,但是这应该为你工作:

c.execute('select * from mytable where id = ANY(%s)', [params]) 

鉴于params = [1, 2, 3, 4, 5],作为结果的SQL将是:

SELECT * FROM mytable where id = ANY(ARRAY[1, 2, 3, 4, 5]) 

注意,这需要ID的列表来弥补的int ,所以如果你有一个字符串列表,一定要先转换它们。

1

已更新答案 对不起,旧的答案。这应该是你想要的,但可能不是最好的解决方案。我尝试了两个参数,一个字符串列表和一个整数列表。

from django.db import connection 

params = [1, 2, 3, '4', '5'] 
placeholders = ('%s,'*len(params)).rstrip(',') # Having a comma at the end will give a syntax error 

with connection.cursor() as cursor: 
    cursor.execute('SELECT * FROM mytable where id IN ({})'.format(placeholders), params) 
    # Use the cursor here 

末更新的答案


在SQL价值为IN需要为您的逗号分隔列表

SELECT column_name(s) 
FROM table_name 
WHERE column_name IN (value1,value2,...); 

所以,最简单的方法,假设params是一个可迭代的将是

from django.db import connection 
with connection.cursor() as cursor: 
    cursor.execute('SELECT * FROM mytable where id IN (%s)', [', '.join(params)]) 

连接会将您的可迭代params转换为一个逗号分隔的字符串,然后将替换%s。

通常你会希望你的查询参数被转义。即使您存储的数据也应该被转义。

编辑:另请注意,我已将光标移至with区块。你应该总是关闭你的连接。 Read up more here

+0

这是错误的答案,会给出不正确的结果。 –

-1

解决方案很简单:

c.execute('select * from mytable where id in (%s)' % (','.join(params),))

查看类似的话题: imploding a list for use in a python MySQLDB IN clause

+0

是的,它是,但上面不使用游标占位符 - 这是相当的解决方法。但是,MySql db处理程序可能在格式化查询中使用命名参数,但在django db处理程序中无法实现。 –

+0

我其实在Django shell中试过它。 –

+0

请注意,这是积极的危险。通过使用正常的字符串格式化,您将引入SQL注入攻击矢量,尤其是如果参数来自任何形式的用户遗留数据。在任何情况下都不要使用此代码。 –