简体   繁体   中英

Searching IN list in python + sqlite3

I am running python with the sqlite3 module and would like to search for rows that match a list. The sql should look like

SELECT column FROM table WHERE column IN (1, 2, 3, 4, 5)

In python, we are recommended to use the ? parameter for value substitution, so this should look like

val_num = [ 1, 2, 3, 4, 5 ]
val_str = ', '.join( [ str(v) for v in val_num ] )

db = sqlite3.connect( filename )   
sql = '''SELECT column FROM table WHERE column IN (?)'''
cur = db.cursor()
cur.execute( sql, (val_str,) )
print( cur.fetch_all() )
cur.close()

This returns an empty list, []

However, if I manually substitute values into the sql statement, which is not advised, it works as expected

val_num = [ 1, 2, 3, 4, 5 ]
val_str = ', '.join( [ str(int(v)) for v in val_num ] )

db = sqlite3.connect( filename )   
sql = '''SELECT column FROM table WHERE column IN ({})'''.format( val_str )
cur = db.cursor()
cur.execute( sql, (val_str,) )
print( cur.fetch_all() )
cur.close()

Which returns [(1,), (2,), (3,), (4,), (5,)]

How do I execute this statement using the API syntax instead of manually substituting values?

Try to use this approach to make the IN operation :

val_num = [ 1, 2, 3, 4, 5 ]

query_str = ''' 
SELECT column FROM table
where
column in  (
''' + ','.join('%s' for i in range(len(val_num))) + ' ) '

cursor.execute(query_str, params=tuple(val_num))
rows = cursor.fetchall()

This is the pseudo-code , not given the statements to make cursor objects n all. just try to change your query-string & the execute line seeing this example - you will get it working.

The placeholder mechansim is here to pass single literal values, not lists. So this:

SELECT column FROM table WHERE column IN (?)

... generates a query where all values are stuffed together in the same literal string, like:

SELECT column FROM table WHERE column IN ('1, 2, 3, 4, 5')

The where predicate is equivalent to: column = '1, 2, 3, 4, 5' , which obviously is not what you want.

You need have one placeholder ( ? ) per value in the list. Here is one way to do it:

sql = 'SELECT column FROM table WHERE column IN ({0})'.format(', '.join('?' for _ in val_num));
cur.execute(sql, val_num);

If the goal is to use server-side parameter substitution you will need to build the query to have the exact amount of ? that you have variables you want to check. The following should achieve that.

val_num = [1, 2, 3, 4, 5]
qs = ", ".join("?" * len(val_num))

query = f"SELECT column FROM table WHERE column IN {qs}"
cur.execute(sql, val_str)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM