Подготовленные Python заявления. Проблемы с SELECT IN - PullRequest
4 голосов
/ 02 июня 2011

У меня проблема с подготовленным оператором в Python, которую я до сих пор не могу решить.

Запрос, который должен быть выполнен, например, ::1003*

 SELECT md5 FROM software WHERE software_id IN (1, 2, 4)

Итак, я попытался выполнить запрос следующим образом:

software_id_string = "(2, 3, 4)"
cursor.execute("SELECT md5 FROM software WHERE software_id IN %s", 
                software_id_string)

Проблема в том, что в строку добавлено '' -> '(2, 3, 4)', так что запрос будет:

SELECT md5 FROM software WHERE software_id IN ''(2, 3, 4)''

Я также пытался перестроить скрипт, как это:

software_id_string = " 1 OR software_id = 2"
cursor.execute("SELECT md5 FROm software WHERE software_id = %s", 
              software_id_string)

Это работает только для первого идентификатора, который будет отправлен (в данном случае 1), потому что часть OR не будет интерпретироваться как оператор SQL ...

Есть ли возможность исправить проблемы с подготовленными заявлениями?

Ответы [ 3 ]

6 голосов
/ 02 июня 2011

Вам нужен один заполнитель для каждого элемента в вашем списке параметров.
Вы можете использовать строковые операции для выполнения этой части:

  1. Создать по одному %s для каждого параметра и
  2. Объедините их вместе с запятой.

На следующем шаге вы можете передать два аргумента в execute(), как рекомендовано в документации DB-API .

software_id_string = (1,2,4)
qry = '''SELECT md5 
           FROM software 
          WHERE software_id IN (%s)''' % ','.join(['%s']*len(software_id_string))
# // 'SELECT md5 FROM software WHERE software_id IN (%s,%s,%s)'
cursor.execute(qry, software_id_string)
2 голосов
/ 02 июня 2011

Я рекомендую создать конвертер типов для явной обработки предложений IN.Вот как модуль psycopg2 обрабатывает его:

from MySQLdb.converters import conversions

class SQL_IN(object):
    def __init__(self, seq):
        self.seq = seq

    @classmethod
    def escape(cls, obj, d):
        return '(' + ','.join((d[type(o)](o, d) for o in obj.seq)) + ')'

# add this before you call MySQLdb.connect()
conversions[SQL_IN] = SQL_IN.escape

Реальный пример:

db = MySQLdb.connect()
cursor = db.cursor()

SQL = "SELECT * FROM emp WHERE emp_id IN %s"
in_values = (1, 2, 3)
cursor.execute(SQL, (SQL_IN(in_values),))
print cursor._last_executed
print cursor.fetchall()

SQL = "SELECT * FROM emp WHERE name IN %s"
in_values = ("bob", "fred")
cursor.execute(SQL, (SQL_IN(in_values),))
print cursor._last_executed
print cursor.fetchall()

Выход:

SELECT * FROM emp WHERE emp_id IN (1,2,3)
((1L, 'bob'), (2L, 'larry'), (3L, 'fred'))
SELECT * FROM emp WHERE name IN ('bob','fred')
((1L, 'bob'), (3L, 'fred'))
0 голосов
/ 02 июня 2011

Вы хотите

cursor.execute("SELECT md5 FROM software WHERE software_id IN %s" % software_id_string)

то есть% вместо запятой

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...