【问题标题】:How does this ActiveRecord 'where' clause work?这个 ActiveRecord 'where' 子句是如何工作的?
【发布时间】:2012-05-16 01:22:36
【问题描述】:

我有这样的声明:

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

它返回true,因为有一个与statusid匹配的orderstatus。

接下来我有:

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

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

那么我有:

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

这返回真。

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

【问题讨论】:

  • 在您的日志中查看第二条语句生成的查询。如果它没有对您的问题提供解释,也请在此处发布。

标签: ruby-on-rails activerecord rails-activerecord


【解决方案1】:

您遇到了 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() 对查询没有任何作用。结果是,就数据库而言,第一个和第三个查询是相同的。

【讨论】:

  • 谢谢,这是有道理的。谢谢你解释清楚。
猜你喜欢
  • 1970-01-01
  • 2018-12-16
  • 1970-01-01
  • 2021-12-01
  • 2011-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-24
相关资源
最近更新 更多