从示例where-col-in example和this answer开始,WHERE IN
子句应该使用带有以下语法的参数进行查询
const response = await db.any('SELECT * FROM table WHERE id IN ($1:csv)', [data])
其中data是数组。
现在,当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
库报告的similar error有knex
和红宝石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
查询可以处理空数组作为参数的最佳方法是什么?
答案 0 :(得分:3)
我是否要在这里添加我自己的答案,因为有一个已被接受,但作为pg-promise的作者,我有点必须,所以这里是...... < / p>
库pg-promise让您可以完全自由地生成所需的任何SQL,它不会以任何方式验证或控制它,因为它不是ORM。
CSV Filter是通用的,它可以在各种上下文中用于生成查询。因此,当您专门用于IN ($1:csv)
时,它并不知道它,并再次生成通用输出。
根据我在this issue中留下的评论,唯一正确的方法是检查数组中是否有任何数据,如果没有,则根本不生成查询。首先,查询将无效,即使您使用一些空逻辑对其进行修补,也意味着它不会生成任何结果,因此查询无论如何都是毫无意义的。
let response = [];
if (data.length) {
response = await db.any('SELECT * FROM table WHERE id IN ($1:csv)', [data]);
}
答案 1 :(得分: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
:)
针对某些框架
您可以查看其手册以查看是否有某种方法来处理空列表,例如:框架是否可以用不存在的值替换空列表?