2012-05-16 2 views
1

У меня это заявление:Как работает это предложение ActiveRecord 'where'?

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

Он возвращает истину, поскольку существует OrderStatus, что соответствует StatusID.

Следующая У меня есть:

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

Это возвращает ложь, где я думал, что это может вернуться верно, так как нет никаких идентификаторов, которые являются нулевыми.

Тогда у меня есть:

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

Это возвращает истину.

Мой вопрос: почему средний оператор возвращает false? Он не жалуется и не делает никаких ошибок. Наверное, я использую нуль, но может кто-нибудь объяснить?

+0

Посмотрите в свой журнал на запрос, сгенерированный вторым оператором. Если это не объясняет ваш вопрос, отправьте его здесь. –

ответ

4

У вас возникли проблемы с NULL SQL. where в средней:

where('id not in (?)', nil) 

становится это SQL:

id not in (null) 

и это эквивалентно следующему:

id != null 

Но результат id != null не является ни истинным, ни ложным, результатом является NULL, а NULL в булевом контексте - false; фактически, 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 «s аргумент синтаксический логика будет игнорировать nil полностью и where(nil) будет такой же, как where() и where() вообще ничего не делает все к запросу , В результате первый и третий запросы идентичны в отношении базы данных.

+0

Спасибо, это имеет смысл. Спасибо, что объяснили это ясно. – dtc

Смежные вопросы