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) |
最简单的方法是先将列表转到
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) |
我希望这可以帮助!!!
您想要的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)) |
如果不太聪明和不太笼统,我会觉得这更直接。这里
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)]) |
即只需确保您将
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),)) |