WHERE col IN Запрос с пустым массивом в качестве параметра

Из примера where-col-in пример и этот ответ, предложения WHERE IN должны иметь запрос с параметрами со следующим синтаксисом

const response = await db.any('SELECT * FROM table WHERE id IN ($1:csv)', [data])

где данные - это массив.

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

 SELECT * FROM users WHERE id IN ()

что является синтаксической ошибкой.

Рассмотрим следующие утверждения:

  • это работает

    const x = await db.any('SELECT * FROM table WHERE id IN ($1:csv)', [[1, 2, 3]]);
    
  • это не работает

    const y = await db.any('SELECT * FROM table WHERE id IN ($1:csv)', [[]]);
    

похожая ошибка, о которой сообщается для библиотеки squel, содержит ответы о том, как knex и ruby ​​sequel ведут себя в таком сценарии. .

Это баг или я что-то не так делаю? Может ли быть альтернативный синтаксис, который работает для обоих сценариев.


Например, альтернативный запрос с использованием ANY работает в обеих ситуациях:

await db.any(`SELECT * FROM table WHERE id = ANY($1)`, [[1, 2, 3]]);
await db.any(`SELECT * FROM table WHERE id = ANY($1)`, [[]]);

Каким должен быть лучший способ иметь запросы WHERE col IN, которые также могут обрабатывать пустые массивы в качестве параметров?


person Naisheel Verdhan    schedule 09.03.2018    source источник


Ответы (2)


Общий ответ

Это баг или я что-то не так делаю?

Не ошибка, а недостаток большинства SQL-фреймворков. Обрабатывать такие параметры очень сложно, поэтому большинство фреймворков просто оставляют пустой список, поскольку это приводит к созданию недопустимого SQL XXX in ().

Может ли быть альтернативный синтаксис, который работает для обоих сценариев.

Простой подход:

if(data is empty) data = [ -1 ]   //fill a non-existing id
db.any('SELECT * FROM table WHERE id IN ($1:csv)', [data])

Как насчет knex или sequel?

Это фреймворки Query Builder, поэтому они могут генерировать специальный SQL для обработки пустых списков. Популярные методы, используемые платформами Query Builder для обработки WHERE id in () OR ...:

  • ГДЕ (id!=id) ИЛИ...
  • ГДЕ (1=0) ИЛИ...
  • ГДЕ (1!=1) ИЛИ...
  • ГДЕ ложно ИЛИ...
  • так далее

Лично мне не нравится id!=id :)

Для некоторых фреймворков

Вы можете проверить его руководство, чтобы узнать, есть ли способ обработки пустых списков, например: может ли фреймворк заменить пустой список несуществующим значением?

person shawn    schedule 09.03.2018

Библиотека pg-promise дает вам полную свободу в создании любого SQL-запроса. проверять или контролировать его каким-либо образом, так как это не ORM.

CSV-фильтр является общим, его можно использовать в различном контексте для создания запросы. Поэтому, когда вы используете его специально для IN ($1:csv), он этого не знает и снова выдает общий вывод.

Согласно комментариям, которые я оставил в этой проблеме, правильный подход таков: проверить, есть ли у вас какие-либо данные в вашем массиве, а если нет — вообще не выполнять запрос. Во-первых, запрос будет недействительным, и даже если вы пропатчите его с какой-то пустой логикой, это означает, что он не будет генерировать никакого результата, и выполнение такого запроса становится пустой тратой IO.

let result = [];
if (data.length) {
    result = await db.any('SELECT * FROM table WHERE id IN ($1:csv)', [data]);
}
/* else: do nothing */
person vitaly-t    schedule 09.03.2018