从示例 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
和 Rubysequel
在这种情况下的行为方式的答案。
这是一个错误还是我做错了什么?是否有适用于这两种情况的替代语法。
例如,使用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
查询的最佳方法应该是什么,这些查询也可以将空数组作为参数处理?
库 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 */
常见答案
这是一个错误还是我做错了什么?
不是错误,而是大多数SQL框架的缺陷。处理这些参数非常困难,因此大多数框架只是保留空列表以生成无效的 SQLXXX 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
呢?
它们是查询生成器框架,因此它们有机会生成特殊的SQL来处理空列表。查询生成器框架用来处理WHERE id in () OR ...
的常用方法:
- 其中 (id!=id) 或 ...
- 其中 (1=0) 或 ...
- 其中 (1!=1) 或 ...
- 凡是假的或...
- 等
我个人不喜欢id!=id
:)
对于某些框架
您可以查看其手册,看看是否有某种方法可以处理空列表,例如:框架可以用不存在的值替换空列表吗?