此活动记录'where'子句如何工作?



>我有这样的说法:

myuser.orders.exists?(['(orderstatus = ?) ', statusid])

它返回 true,因为存在与状态 ID 匹配的订单状态。

接下来我有:

myuser.orders.where('id not in (?)', nil).exists?(['(orderstatus = ?) ', statusid])

这在我认为它可能返回 true 的地方返回 false,因为没有 id 为 nil。

然后我有:

myuser.orders.where(nil).exists?(['(orderstatus = ?) ', statusid])

这将返回 true。

我的问题是为什么中间的陈述返回 false? 它不会抱怨或抛出任何错误。 我想我用错了 nil,但有人可以解释一下吗?

你在使用 SQL 的 NULL 时遇到了问题。中间的where

where('id not in (?)', nil)

变成这个 SQL:

id not in (null)

这相当于这个:

id != null

但是id != null的结果既不是真的也不是假的,结果是NULL,布尔上下文中的NULL是假的;事实上,x = nullx != null会导致所有x的NULL(即使x本身是NULL(;例如,在PostgreSQL中:

=> select coalesce((11 = null)::text, '-NULL-');
 coalesce 
----------
 -NULL-
(1 row)
=> select coalesce((11 != null)::text, '-NULL-');
 coalesce 
----------
 -NULL-
(1 row)
=> select coalesce((null = null)::text, '-NULL-');
 coalesce 
----------
 -NULL-
(1 row)
=> select coalesce((null != null)::text, '-NULL-');
 coalesce 
----------
 -NULL-
(1 row)

MySQL和其他所有合理兼容的数据库将做同样的事情(可能有不同的转换要求以使NULL显而易见(。

结果是where(id not in (?)', nil)总是产生一个空集,而您的存在检查将始终在空集上失败。

如果你想说"id不是 NULL 的所有行",那么你想说:

where('id is not null')

如果您的id是主键(几乎可以肯定是(,那么id永远不会为 NULL,您可以完全省略该where


当你递where一个nil

where(nil)

where的参数解析逻辑将完全忽略nilwhere(nil)将与where()相同,where()对查询没有任何作用。结果是,就数据库而言,第一个和第三个查询是相同的。

最新更新