Оператор Python / psycopg2 WHERE IN

81

Каков правильный метод, чтобы список (countryList) был доступен через% s в операторе SQL?

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

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

Как и сейчас, он выдает ошибку после попытки запустить "WHERE country in (ARRAY [...])". Есть ли способ сделать это, кроме манипуляций со строками?

благодаря

Мэтт
источник

Ответы:

133

Для INоператора вам нужен кортеж вместо списка и удалите скобки из строки SQL.

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

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

Во время отладки вы можете проверить правильность построения SQL с помощью

cur.mogrify(sql, (data,))
Брайан
источник
Спасибо за быстрый ответ!
Мэтт
1
Если у вас возникли проблемы даже после прочтения этого ответа, перечитайте его снова очень медленно. Это кортеж кортежей, и вы должны удалить параны вокруг% s, если они у вас там есть. Это сбило меня с толку, потому что в моем более простом тесте использовалось только одно значение, и все работало. Просто следуйте этому в точности так, как это написал Брайан.
zachaysan
40

Чтобы немного пояснить ответ и обратиться к именованным параметрам и преобразовать списки в кортежи:

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.
})
Джошуа Бернс
источник
1
Спасибо за подсказку о передаче диктовки. Это намного лучше.
Джек
Можно ли это реализовать с помощью нескольких предложений WHERE x IN и нескольких списков в словаре?
Odisseo
1
Поправка: @Odisseo Да, всемогущим OR. Например: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)})
Джошуа Бернс
12

Вы можете использовать список Python напрямую, как показано ниже. Он действует как оператор IN в SQL, а также обрабатывает пустой список, не вызывая ошибок.

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

источник: http://initd.org/psycopg/docs/usage.html#lists-adaptation

Правеенраджан27
источник
Также можно использовать принятый ответ, но с cur.execute(sql, (tuple(data),))
Адам Хьюз