简体   繁体   中英

Why doesn't this work? WHERE IN

(Not a duplicate. I know that there's a way of doing this that works: Parameter substitution for a SQLite "IN" clause .)

I'd like to know what I'm missing in this code. I build a simple table. Then I successfully copy some of its records to a new table where the records are qualified by a WHERE clause that involves two lists. Having tossed that table I attempt to copy the same records but this time I put the list into a variable which I insert into the sql statement. This time no records are copied.

How come?

import sqlite3

conn = sqlite3.connect(':memory:')
curs = conn.cursor()

oldTableRecords = [ [ 15, 3 ], [ 2, 1], [ 44, 2], [ 6, 9 ] ]

curs.execute('create table oldTable (ColA integer, ColB integer)')
curs.executemany('insert into oldTable (ColA, ColB) values (?,?)', oldTableRecords)

print ('This goes ...')
curs.execute('''create table newTable as 
    select * from oldTable
    where ColA in (15,3,44,9) or ColB in (15,3,44,9)''')

for row in curs.execute('select * from newTable'):
    print ( row)

curs.execute('''drop table newTable''')

print ('This does not ...')
TextTemp = ','.join("15 3 44 9".split())
print (TextTemp)
curs.execute('''create table newTable as 
    select * from oldTable
    where ColA in (?) or ColB in (?)''', (TextTemp,TextTemp))

for row in curs.execute('select * from newTable'):
    print ( row)

Output:

This goes ...
(15, 3)
(44, 2)
(6, 9)
This does not ...
15,3,44,9

TIA!

The whole point of a SQL parameter is to prevent SQL syntax in values from being executed . That includes commas between values; if this wasn't the case then you couldn't ever use values with commas in query parameters and is probably a security issue to boot.

You can't just use one ? to insert multiple values into a query; the whole TextTemp value is seen as one value, producing the following equivalent:

create table newTable as 
select * from oldTable
where ColA in ('15,3,44,9') or ColB in ('15,3,44,9')

None of the values in ColA or ColB have a single row with the string value 15,3,44,9 .

You need to use separate placeholders for each of the values in your parameter:

col_values = [int(v) for v in "15 3 44 9".split()]

placeholders = ', '.join(['?'] * len(col_values))
sql = '''create table newTable as 
    select * from oldTable
    where ColA in ({0}) or ColB in ({0})'''.format(placeholders)

curs.execute(sql, col_values * 2)

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