Генерация SQL «IN» предложений: как безопасно обрабатывать ввод + пустые списки значений? - PullRequest
2 голосов
/ 13 января 2010

В моем коде Python я часто выполняю следующее (используя DB-API):

yValues = pickInterestingValuesOfY()

sql = "..." # includes a clause stating that "y must be in yValues"

c.execute(sql, yValues)

В конце концов, выполняемый SQL может быть таким простым, как

SELECT x FROM table1 WHERE y IN (1,2,3);

Проблема в том, что набор возможных значений для y (1,2,3) определяется во время выполнения.

У меня есть две проблемы:

  1. генерирует допустимый SQL в случае, если yValues ​​пуст («WHERE y IN ()» является недействительным SQL)
  2. следить за внедрением sql, если значения получены из ненадежного источника

Для решения (2) я должен позволить DB-API фактически вставить значения yValues ​​в оператор SQL. Поэтому я получил следующее запутанное решение:

def inClause(columnName, values):

    if len(values):
         placeHolders = ','.join( ['%s'] * len(values) )
         sql = "%s IN (%s)" % (columnName, placeHolders)
    else: 
         sql = "FALSE"
    return "(%s)" % sql

# get a db-api cursor called c
c.execute("SELECT x FROM table1 WHERE %s;" % inClause('y', yValues), yValues)

, который, кажется, правильно решает обе проблемы выше. Однако я не могу поверить, что это неуклюжее решение - то, что нужно.

Как вы обрабатываете такие запросы? Мне не хватает более элегантного способа сделать это?

Я не ищу ORM.

(Я использую MySQL, поэтому, если есть какой-то магический нестандартный переключатель mysql, который молча принимает WHERE y IN () 'как действительный, просто дайте мне знать, и о проблеме (1) позаботятся.)

Ответы [ 4 ]

5 голосов
/ 13 января 2010

Для предложения in просто всегда включайте значение, которого не будет в списке (например, отрицательное целое число).

3 голосов
/ 13 января 2010

Неа. Там нет красивого способа сделать это. DB-API не имеет никакой спецификации для обработки последовательностей таким образом.

0 голосов
/ 11 июля 2014

Для MySQL вы можете сделать это:

SELECT x FROM table1 WHERE y IN (SELECT NULL FROM DUAL WHERE 0);

DUAL - это виртуальная таблица, созданная для этой цели. Это подходит для выбора данных, которые не требуют таблицы. А предложение WHERE 0 гарантирует, что из подзапроса не будет возвращено ни одной записи.

Короче говоря, SELECT NULL FROM DUAL WHERE 0 - идеальная замена пустому списку.

0 голосов
/ 13 января 2010

Не генерируйте свой собственный SQL.

Используйте SQLAlchemy.Это делает это для вас.

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