[英]Active Record NOT IN queries and NULL with MySQL
我有一个查询,如:
Tag.where('id not IN (?)', current_user.tags.pluck(:id)).uniq
什么时候
current_user.tags.pluck(:id)).uniq
返回 NULL,我从标签查询中没有得到任何结果,这不是所需的行为。
我在这里做错了什么?
谢谢。
我不认为current_user.tags.pluck(:id)
正在返回nil
,它返回的是一个空数组。 ActiveRecord 将在该上下文中将空数组视为 NULL 。 结果是一些无意义的 SQL,如下所示:
select tags.* from tags where id in (null)
由于 SQL 的 NULL 的特性(特别是x = NULL
和x != NULL
对于所有x
都是假的),WHERE 子句中的in (null)
或not in (null)
不会匹配任何内容。
Rails 将 Ruby 的[]
转换为NULL
非常愚蠢(此处有更多讨论),但即使它足够聪明以引发异常,您仍然必须使用以下内容手动处理“空数组”情况:
tag_ids = current_user.tags.pluck(:id)
if(tag_ids.empty?)
tags = Tag.all
else
tags = Tag.where('id not in (?)', tag_ids)
end
而且您不需要那里的uniq
,SQL in
运算符会将其 RHS 视为一个集合,因此重复项将在幕后折叠。
where.not
让 Rails 处理。 由于mu 太短指出,当传递给查询条件的值是一个空数组时,ActiveRecord 会将其转换为NULL
,这会扰乱您的查询并始终返回空结果。
处理这个问题的旧方法是有条件地检查一个空数组作为参数,而不是添加这个条件。 但是,随着 Rails 4 引入where.not
,我们不再需要进行此检查。
我们可以简单地做:
Tag.where.not( id: current_user.tags.pluck(:id) ).uniq
现在 ActiveRecord 将自动检查一个空数组,当它看到它时,条件变为1=1
,这本质上是无意义的,但更重要的是,它只是被忽略,其余的查询将运行,就好像从未添加过该条件一样到查询。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.