繁体   English   中英

Active Record NOT IN 查询和 NULL 与 MySQL

[英]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 = NULLx != 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM