您遇到了 SQL 的 NULL 问题。where
中间那个:
where('id not in (?)', nil)
变成这个 SQL:
id not in (null)
这相当于:
id != null
但结果id != null
既非真非假,结果为 NULL 且布尔上下文中的 NULL 为假;事实上,x = null
并x != null
导致所有人都为 NULL x
(即使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()
根本不执行任何操作。结果是就数据库而言,第一个和第三个查询是相同的。