2013-07-16 1 views
17

Я растерялась за рассуждение о следующем:Почему PostgreSQL не возвращает нулевые значения, когда условие <> верно

SELECT * FROM table WHERE avalue is null 

Возвращает й количество строк, где «Avalue» является нулевым

SELECT * FROM table WHERE avalue <> true 

Делает не возвращает строки, где 'avalue' равно null.

Мои рассуждения (что представляется неверным) является то, что null представляет собой уникальное значение (это даже не равно null) означает, что он должен показать в наборе результатов, как это не равно true либо.

Я думаю, вы могли бы утверждать, что, сказав column <> value, вы подразумеваете, что столбец имеет значение, поэтому игнорирует значения null.

Какова причина этого, и это то же самое в других распространенных SQL DB?

Мое рассуждение (предположение) говорит мне, что это противоречит интуиции, и я хотел узнать почему.

+8

[трехзначной логики] (http://en.wikipedia.org/wiki/Three-valued_logic). Вы предполагаете, что единственными возможными ответами на '<>' являются 'true' или' false', тогда как в SQL существует опция 'unknown'. Это соответствует стандартам. (Смутно, MySQL объединяет 'UNKNOWN' и' NULL', так что там возможны возможные «TRUE», «FALSE» и «NULL»). –

+1

SQL Server делает это точно так же. – Fanda

+0

Как говорит Дэмиен ... Это обычно называют трехзначной логикой. – Kuberchaun

ответ

27

Каждый полпути приличным RDBMS делает его таким же образом, потому что это правильный.
Я цитирую the Postgres manual here:

Обычных операторы сравнения выхода нуль (означающее «неизвестно»), не истинные или ложные, когда либо вход нуля. Например, 7 = NULL дает null, равно как 7 <> NULL.Когда такое поведение не подходит, используйте IS [ NOT ] DISTINCT FROM конструкции:

expression IS DISTINCT FROM expression 
expression IS NOT DISTINCT FROM expression 

Обратите внимание, что эти выражения выполняют немного медленнее, чем простой expression <> expression сравнения.

Для значений boolean существует также более простой IS NOT [TRUE | FALSE].
Чтобы получить то, что вы ожидали в вашем втором запросе написать:

SELECT * FROM table WHERE avalue IS NOT TRUE;

SQL Fiddle.

+0

ИМХО, это ошибочная логика, а не «правильная». Если я сравню 7 с NULL, ответ не должен быть неизвестным, ответ должен быть ложным. Это логика сгибания SQL. В любом случае, спасибо за отличный ответ, «IS DISTINCT FROM» сохранил этот день. – sandre89

+1

@ sandre89 Проблема в том, что вы не можете определить оператор, который объединяет или сравнивает NULL (или «неизвестный») с чем-либо еще. Каким должен быть результат для '7> NULL' или' 7 NULL' не имеет смысла, и поэтому результат неизвестен (который представлен как« NULL'). –

+0

@WizardofOgz Я согласен, что 7> NULL не имеет смысла. Но 7 <> NULL истинно, и нет никакого способа обойти это: это другое. Точно так же 7 = NULL должен быть ложным. – sandre89

2

Это нормально. SQL Server делает это точно так же. В SQL Server можно использовать

SELECT * FROM table WHERE ISNULL(avalue, 0) <> 1 

Для PostGreSQL эквивалент смотреть это: What is the PostgreSQL equivalent for ISNULL()

Рассмотрим использовать NOT NULL спецификацию столбца со значением по умолчанию, если это имеет смысл.

EDIT:

Я думаю, что это логика. NULL не является значением, поэтому он исключается из поиска - вы должны указать его явно. Если разработчики SQL решают пойти вторым путем (включая нули автоматически), то вы получите больше проблем, если вам нужно распознать значения

4

This link дает полезную информацию. Фактически, как указывает @Damien_The_Unbeliever, он использует трехзначную логику и, кажется, (согласно статье) предмет обсуждения.

Несколько других хороших ссылок можно найти here и here.

Я думаю, что это сводится к null, не являющемуся значением, но владелец места для ценности и решение должны быть сделаны, и это было ... так что NULL не равно никакому значению, потому что это не значение и даже не будет равно какой-либо ценности .... если это имеет смысл.

+0

Статья в простой-talk содержит ошибку с таблицей AND. В нем говорится, что «false AND unknown is unknown», когда оно должно быть «false AND unknown is false». Подобно «неизвестному и ложному», он должен быть «ложным». Это обсуждается в комментариях к статье, но статья не обновляется. – mangoDrunk

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