我有这样的声明:
myuser.orders.exists?(['(orderstatus = ?) ', statusid])
它返回true,因为有一个与statusid匹配的orderstatus。
接下来我有:
myuser.orders.where('id not in (?)', nil).exists?(['(orderstatus = ?) ', statusid])
这会返回false,我认为它可能会返回true,因为没有id为nil。
然后我有:
myuser.orders.where(nil).exists?(['(orderstatus = ?) ', statusid])
返回true。
我的问题是为什么中间语句会返回false?它不会抱怨或抛出任何错误。我想我使用的是nil错误,但有人可以解释一下吗?
答案 0 :(得分:4)
你遇到SQL的NULL问题。中间的where
:
where('id not in (?)', nil)
成为这个SQL:
id not in (null)
这相当于:
id != null
但是id != null
的结果既不是真也不是假,结果是NULL并且布尔上下文中的NULL为false;事实上,x = null
和x != 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
的参数解析逻辑将完全忽略nil
,而where(nil)
将与where()
相同而where()
对此无效查询。结果是,就数据库而言,第一个和第三个查询是相同的。