检索空数组记录时的问题
问题:检索空数组记录时的问题 我有一个大约 100 个用户的表,我还有一个用户 ID 数组。我想要做的是显示所有不属于这个用户 ID 数组的用户。当我做这样的事情 User.where('id NOT IN (?)', [9, 2, 3, 4]) 它成功返回了用户 id 不属于该数组的记录。但是,如果该数组像这样为空 User.where('id NOT IN (?)', []) 它不会返回任何用
问题:检索空数组记录时的问题
我有一个大约 100 个用户的表,我还有一个用户 ID 数组。我想要做的是显示所有不属于这个用户 ID 数组的用户。当我做这样的事情
User.where('id NOT IN (?)', [9, 2, 3, 4])
它成功返回了用户 id 不属于该数组的记录。但是,如果该数组像这样为空
User.where('id NOT IN (?)', [])
它不会返回任何用户,SQL 查询看起来像这样
SELECT "users".* FROM "users" WHERE (id NOT IN (NULL))
有谁知道为什么会发生这种情况,或者这可能是一个错误?我正在使用带有 PostgreSQL 的 Rails 3.2.5。
解答
ActiveRecord(至少 3.2.1)将空数组视为 NULL。where
调用中的占位符由sanitize_sql
处理。如果您稍微跟踪一下代码,您将来到replace_bind_variables
:
def replace_bind_variables(statement, values) #:nodoc:
raise_if_bind_arity_mismatch(statement, statement.count('?'), values.size)
bound = values.dup
c = connection
statement.gsub('?') { quote_bound_value(bound.shift, c) }
end
然后是quote_bound_value
:
def quote_bound_value(value, c = connection) #:nodoc:
if value.respond_to?(:map) && !value.acts_like?(:string)
if value.respond_to?(:empty?) && value.empty?
c.quote(nil)
else
value.map { |v| c.quote(v) }.join(',')
end
else
c.quote(value)
end
end
一个空数组将满足所有四个条件,让您到达c.quote(nil)
,这就是您的 NULL 的来源。所有导致c.quote(nil)
的特殊逻辑都表明这是故意行为。
用空列表说 IN(或 NOT IN):
where c in ()
应该会产生一个 SQL 错误,所以也许 AR 人员正试图通过悄悄地将那个坏 SQL 变成c in (null)
来防止这种情况发生。请注意,这些都不是:
select ... from t where c in (null);
select ... from t where c not in (null);
由于 SQL 的 NULL 的行为,应该永远产生任何结果。这是一个典型的新手错误,AR 人真的应该知道得更多。
我自己更喜欢一个例外:告诉我我将要部署一个脚子弹比只是给我一把不同的枪要友好得多。
执行摘要:
1.这种“空数组表示NULL”的行为是故意的。
-
你永远不应该尝试
where('c in (?)', [])
或where('c not in (?)', [])
,因为这两种说法都没有多大意义。 -
更新您的 Ruby 代码以检查空数组并做任何需要做的事情以获得您期望的结果。
更多推荐
所有评论(0)