Instrukcja Python / psycopg2 WHERE IN

81

Jaka jest właściwa metoda, aby lista (countryList) była dostępna za pośrednictwem% sw instrukcji SQL?

# using psycopg2
countryList=['UK','France']

sql='SELECT * from countries WHERE country IN (%s)'
data=[countryList]
cur.execute(sql,data)

Jak to jest teraz, wyświetla błąd po próbie uruchomienia "WHERE country in (ARRAY [...])". Czy jest na to inny sposób niż manipulacja ciągiem?

Dzięki

Matt
źródło

Odpowiedzi:

133

Dla INoperatora chcesz krotkę zamiast listy i usunąć nawiasy z ciągu SQL.

# using psycopg2
data=('UK','France')

sql='SELECT * from countries WHERE country IN %s'
cur.execute(sql,(data,))

Podczas debugowania możesz sprawdzić, czy SQL jest poprawnie zbudowany z

cur.mogrify(sql, (data,))
Bryan
źródło
Dziękuję za szybką odpowiedź!
Matt
1
Jeśli masz problemy nawet po przeczytaniu tej odpowiedzi, przeczytaj ją ponownie, bardzo powoli. To jest krotka krotek i musisz usunąć parany wokół% s, jeśli je tam masz. To mnie zaskoczyło, ponieważ mój prostszy test używał tylko jednej wartości i wszystko działało. Po prostu postępuj zgodnie z tym, co napisał Bryan.
zachaysan
40

Aby trochę wyjaśnić odpowiedź, zająć się nazwanymi parametrami i przekonwertować listy na krotki:

countryList = ['UK', 'France']

sql = 'SELECT * from countries WHERE country IN %(countryList)s'

cur.execute(sql, { # You can pass a dict for named parameters rather than a tuple. Makes debugging hella easier.
    'countryList': tuple(countryList), # Converts the list to a tuple.
})
Joshua Burns
źródło
1
Dziękuję za wskazówkę dotyczącą przekazania dyktu. To jest dużo lepsze.
Jack
Czy można to zaimplementować z wieloma klauzulami WHERE x IN i wieloma listami w słowniku?
Odisseo
1
Korekta: @Odisseo Tak, z wszechmocnym OR. Np .:cur.execute("SELECT * FROM table WHERE col IN %(list1)s OR col IN %(list2)s", {'list1': tuple(1,2,3), 'list2' = tuple(4,5,6)})
Joshua Burns
12

Możesz użyć listy Pythona bezpośrednio, jak poniżej. Działa jak operator IN w SQL, a także obsługuje pustą listę bez zgłaszania żadnego błędu.

data=['UK','France']
sql='SELECT * from countries WHERE country = ANY (%s)'
cur.execute(sql,(data,))

źródło: http://initd.org/psycopg/docs/usage.html#lists-adaptation

Praveenrajan27
źródło
Można również użyć zaakceptowanej odpowiedzi, ale z cur.execute(sql, (tuple(data),))
Adam Hughes