sql查询中的python列表作为参数

python list in sql query as parameter

我有一个python列表,说我

1
l = [1,5,8]

我想编写一个SQL查询来获取列表中所有元素的数据,例如

1
select name from students where id = |IN THE LIST l|

我该如何完成?


到目前为止,答案一直是将这些值模板化为纯SQL字符串。这对于整数绝对没问题,但是如果我们想对字符串进行处理,则会遇到转义问题。

这是一个使用参数化查询的变体,它对两个都适用:

1
2
3
4
placeholder= '?' # For SQLite. See DBAPI paramstyle.
placeholders= ', '.join(placeholder for unused in l)
query= 'SELECT name FROM students WHERE id IN (%s)' % placeholders
cursor.execute(query, l)


最简单的方法是先将列表转到tuple

1
2
t = tuple(l)
query ="select name from studens where id IN {}".format(t)


不要使其复杂化,为此的解决方案很简单。

1
2
3
4
5
6
7
l = [1,5,8]

l = tuple(l)

params = {'l': l}

cursor.execute('SELECT * FROM table where id in %(l)s',params)

enter image description here

我希望这可以帮助!!!


您想要的SQL是

1
select name from studens where id in (1, 5, 8)

如果您想从python构造它,可以使用

1
2
l = [1, 5, 8]
sql_query = 'select name from studens where id in (' + ','.join(map(str, l)) + ')'

map函数会将列表转换为字符串列表,可以使用str.join方法将这些字符串用逗号粘合在一起。

或者:

1
2
l = [1, 5, 8]
sql_query = 'select name from studens where id in (' + ','.join((str(n) for n in l)) + ')'

如果您更喜欢生成器表达式而不是map函数。

更新:S. Lott在评论中提到Python SQLite绑定不支持序列。在这种情况下,您可能需要

1
select name from studens where id = 1 or id = 5 or id = 8

产生者

1
sql_query = 'select name from studens where ' + ' or '.join(('id = ' + str(n) for n in l))


string.join用逗号分隔的列表值,并使用format运算符形成查询字符串。

1
myquery ="select name from studens where id in (%s)" %",".join(map(str,mylist))

(谢谢布莱尔·康拉德)


我喜欢bobince的回答:

1
2
3
4
placeholder= '?' # For SQLite. See DBAPI paramstyle.
placeholders= ', '.join(placeholder for unused in l)
query= 'SELECT name FROM students WHERE id IN (%s)' % placeholders
cursor.execute(query, l)

但是我注意到了这一点:

1
placeholders= ', '.join(placeholder for unused in l)

可以替换为:

1
placeholders= ', '.join(placeholder*len(l))

如果不太聪明和不太笼统,我会觉得这更直接。这里l必须具有长度(即,引用定义__len__方法的对象),这应该不成问题。但是占位符也必须是单个字符。要支持多字符占位符使用:

1
placeholders= ', '.join([placeholder]*len(l))


@umount答案的解决方案,因为它用一个元素的元组中断了,因为(1,)不是有效的SQL。

1
2
3
4
5
6
7
8
9
>>> random_ids = [1234,123,54,56,57,58,78,91]
>>> cursor.execute("create table test (id)")
>>> for item in random_ids:
    cursor.execute("insert into test values (%d)" % item)
>>> sublist = [56,57,58]
>>> cursor.execute("select id from test where id in %s" % str(tuple(sublist)).replace(',)',')'))
>>> a = cursor.fetchall()
>>> a
[(56,), (57,), (58,)]

sql字符串的其他解决方案:

1
cursor.execute("select id from test where id in (%s)" % ('"'+'","'.join(l)+'"'))


例如,如果要使用sql查询:

1
select name from studens where id in (1, 5, 8)

关于什么:

1
2
my_list = [1, 5, 8]
cur.execute("select name from studens where id in %s" % repr(my_list).replace('[','(').replace(']',')') )

如果您将PostgreSQL与Psycopg2库一起使用,则可以让其元组适应为您完成所有转义和字符串插值,例如:

1
2
3
4
ids = [1,2,3]
cur.execute(
 "SELECT * FROM foo WHERE id IN %s",
  [tuple(ids)])

即只需确保您将IN参数作为tuple传递。如果它是list,则可以使用= ANY数组语法:

1
2
3
cur.execute(
 "SELECT * FROM foo WHERE id = ANY (%s)",
  [list(ids)])

请注意,这两个都将变成相同的查询计划,因此您应该只使用较容易的那个。例如如果您的列表位于一个元组中,则使用前者;如果它们存储在列表中,则使用后者。


一个更简单的解决方案:

1
2
3
lst = [1,2,3,a,b,c]

query = f"""SELECT * FROM table WHERE IN {str(lst)[1:-1}"""

1
2
3
4
placeholders= ', '.join("'{"+str(i)+"}'" for i in range(len(l)))
query="select name from students where id (%s)"%placeholders
query=query.format(*l)
cursor.execute(query)

这应该可以解决您的问题。


这使用参数替换并处理单个值列表的情况:

1
2
3
4
5
6
7
8
l = [1,5,8]

get_operator = lambda x: '=' if len(x) == 1 else 'IN'
get_value = lambda x: int(x[0]) if len(x) == 1 else x

query = 'SELECT * FROM table where id ' + get_operator(l) + ' %s'

cursor.execute(query, (get_value(l),))