WHERE col IN 以空数组为参数查询
WHERE col IN Query with empty array as parameter
来自示例 where-col-in example and ,WHERE IN
子句应具有具有以下语法参数的查询
const response = await db.any('SELECT * FROM table WHERE id IN (:csv)', [data])
其中数据是数组。
现在,当数据为空数组时,它会生成以下查询
SELECT * FROM users WHERE id IN ()
这是语法错误。
考虑以下陈述:
这个有效
const x = await db.any('SELECT * FROM table WHERE id IN (:csv)', [[1, 2, 3]]);
这行不通
const y = await db.any('SELECT * FROM table WHERE id IN (:csv)', [[]]);
为 squel
库报告的 similar error 回答了 knex
和 ruby 的 sequel
在这种情况下的行为。
这是一个错误还是我做错了什么?是否有适用于这两种情况的替代语法。
例如,使用 ANY
的备用查询适用于两种情况:
await db.any(`SELECT * FROM table WHERE id = ANY()`, [[1, 2, 3]]);
await db.any(`SELECT * FROM table WHERE id = ANY()`, [[]]);
让 WHERE col IN
查询也可以将空数组作为参数处理的最佳方式应该是什么?
常见答案
Is this a bug or am I doing something wrong?
不是错误,而是大多数 SQL 框架的缺陷。处理这样的参数非常困难,所以大多数框架只是留下空列表,因为它会生成无效的 SQL XXX in ()
.
Could there be an alternate syntax which works for both scenarios.
一个简单的方法是:
if(data is empty) data = [ -1 ] //fill a non-existing id
db.any('SELECT * FROM table WHERE id IN (:csv)', [data])
knex
或sequel
呢?
它们是查询生成器框架,因此它们有机会生成特殊的 SQL 来处理空列表。 Query Builder 框架用来处理 WHERE id in () OR ...
:
的流行方法
- 哪里 (id!=id) 或 ...
- 哪里 (1=0) 或 ...
- 哪里 (1!=1) 或 ...
- 哪里为假或...
- 等等
个人不喜欢id!=id
:)
对于某些框架
您可以查看它的手册,看看是否有一些方法可以处理空列表,例如:框架可以用 non-existing 值替换空列表吗?
库 pg-promise 让您完全自由地生成任何您想要的 SQL,它不会以任何方式验证或控制它,因为它不是 ORM。
CSV Filter 是通用的,它可以在各种上下文中用于生成查询。因此,当您专门针对 IN (:csv)
使用它时,它并不知道,并再次生成通用输出。
根据我在 this issue 中留下的评论,正确的方法是检查数组中是否有任何数据,如果没有 - 根本不要执行查询。首先,查询是无效的,即使你用一些空逻辑来修补它,也意味着它不会产生任何结果,执行这样的查询会浪费 IO。
let result = [];
if (data.length) {
result = await db.any('SELECT * FROM table WHERE id IN (:csv)', [data]);
}
/* else: do nothing */
来自示例 where-col-in example and WHERE IN
子句应具有具有以下语法参数的查询
const response = await db.any('SELECT * FROM table WHERE id IN (:csv)', [data])
其中数据是数组。
现在,当数据为空数组时,它会生成以下查询
SELECT * FROM users WHERE id IN ()
这是语法错误。
考虑以下陈述:
这个有效
const x = await db.any('SELECT * FROM table WHERE id IN (:csv)', [[1, 2, 3]]);
这行不通
const y = await db.any('SELECT * FROM table WHERE id IN (:csv)', [[]]);
为 squel
库报告的 similar error 回答了 knex
和 ruby 的 sequel
在这种情况下的行为。
这是一个错误还是我做错了什么?是否有适用于这两种情况的替代语法。
例如,使用 ANY
的备用查询适用于两种情况:
await db.any(`SELECT * FROM table WHERE id = ANY()`, [[1, 2, 3]]);
await db.any(`SELECT * FROM table WHERE id = ANY()`, [[]]);
让 WHERE col IN
查询也可以将空数组作为参数处理的最佳方式应该是什么?
常见答案
Is this a bug or am I doing something wrong?
不是错误,而是大多数 SQL 框架的缺陷。处理这样的参数非常困难,所以大多数框架只是留下空列表,因为它会生成无效的 SQL XXX in ()
.
Could there be an alternate syntax which works for both scenarios.
一个简单的方法是:
if(data is empty) data = [ -1 ] //fill a non-existing id
db.any('SELECT * FROM table WHERE id IN (:csv)', [data])
knex
或sequel
呢?
它们是查询生成器框架,因此它们有机会生成特殊的 SQL 来处理空列表。 Query Builder 框架用来处理 WHERE id in () OR ...
:
- 哪里 (id!=id) 或 ...
- 哪里 (1=0) 或 ...
- 哪里 (1!=1) 或 ...
- 哪里为假或...
- 等等
个人不喜欢id!=id
:)
对于某些框架
您可以查看它的手册,看看是否有一些方法可以处理空列表,例如:框架可以用 non-existing 值替换空列表吗?
库 pg-promise 让您完全自由地生成任何您想要的 SQL,它不会以任何方式验证或控制它,因为它不是 ORM。
CSV Filter 是通用的,它可以在各种上下文中用于生成查询。因此,当您专门针对 IN (:csv)
使用它时,它并不知道,并再次生成通用输出。
根据我在 this issue 中留下的评论,正确的方法是检查数组中是否有任何数据,如果没有 - 根本不要执行查询。首先,查询是无效的,即使你用一些空逻辑来修补它,也意味着它不会产生任何结果,执行这样的查询会浪费 IO。
let result = [];
if (data.length) {
result = await db.any('SELECT * FROM table WHERE id IN (:csv)', [data]);
}
/* else: do nothing */