tags:

views:

1344

answers:

5

I have a python list, say l

l = [1,5,8]

I want to write a sql query to get the data for all the elements of the list, say

"select name from studens where id = |IN THE LIST l|"

How do i accomlish this?

+1  A: 

string.join the list values separated by commas, and use the format operator to form a query string.

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

(Thanks, blair-conrad)

gimel
This will fail since l is a list of integers, not strings.
Blair Conrad
+2  A: 

The SQL you want is

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

If you want to construct this from the python you could use

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

The map function will transform the list into a list of strings that can be glued together by commas using the str.join method.

Alternatively:

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

if you prefer generator expressions to the map function.

UPDATE: S. Lott mentions in the comments that the Python SQLite bindings doing support sequences. In that case, you might want

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

Generated by

sql_query = 'select name from studens where ' + ' or '.join(('id = ' + str(n) for n in l))
Blair Conrad
:-( Python SQLite binding doesn't support sequences.
S.Lott
Oh? I didn't realize. Then again, I didn't realize we were going for a SQLite binding solution.
Blair Conrad
Sorry, not suggesting or implying SQLite -- just sad that bindings for lists don't work there.
S.Lott
+1  A: 

Here is one way, where cursor is your usual cursor object:

>>> 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)))
>>> a = cursor.fetchall()
>>> a
[(56,), (57,), (58,)]
bvmou
Cute. It wouldn't have occurred to me to rely on the fact that tuple formats like SQL's list syntax.
Blair Conrad
+11  A: 

Answers so far have been templating the values into a plain SQL string. That's absolutely fine for integers, but if we wanted to do it for strings we get the escaping issue.

Here's a variant using a parameterised query that would work for both:

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)
bobince
A: 

But what if list is too long and kinterbasdb raises this:

ProgrammingError: (0L, 'SQL statement of 80316 bytes is too long (max 65535 allowed). Consider using bound parameters to shorten the SQL code, rather than passing large values as part of the SQL string.')

Any ideas except that optimizing code?