SQL не отображает нулевые значения в запросе не равно?
Это просто вопрос из любопытства, но я смотрю на базу данных и вытаскиваю данные из таблицы с запросом на один из столбцов. Столбец имеет четыре возможных значения null
, 0
, 1
, 2
. Когда я запускаю запрос как:
SELECT * FROM STATUS WHERE STATE != '1' AND STATE != '2';
Я получаю те же результаты, что и при запуске:
SELECT * FROM STATUS WHERE STATE = '0';
т.е. строки с нулевым значением в верхней команде в столбце queried, кажется, не указаны в результатах, всегда ли это происходит в SQL?
Я запускаю свои команды через Oracle SQL Developer.
Ответы
Ответ 1
В нескольких языках NULL обрабатывается по-разному: большинство людей знают о двузначной логике, где true
и false
являются единственными сопоставимыми значениями в булевых выражениях (даже если false определяется как 0 и true как что-либо еще).
В стандартном SQL вы должны думать о трехзначной логике. NULL не рассматривается как реальная ценность, вы можете назвать его "неизвестным". Поэтому, если значение неизвестно, неясно, есть ли в вашем случае state
0, 1 или что-то еще. Итак, NULL != 1
снова возвращается к NULL
.
Это делает вывод о том, что если вы отфильтровываете что-то, что может быть NULL, вам нужно лечить значения NULL самостоятельно. Обратите внимание, что синтаксис также различен: значения NULL можно сравнить только с x IS NULL
вместо x = NULL
. См. Википедию для таблицы истинности, показывающей результаты логических операций.
Ответ 2
Да, это нормально, возможно, вы установили, что настройки базы данных исправлены, что
Но вы можете изменить свой код и сделать что-то вроде этого:
SELECT * FROM STATUS WHERE STATE != '1' OR STATE != '2' or STATE is null;
Посмотрите на это для получения дополнительной информации:
http://www.w3schools.com/sql/sql_null_values.asp
Ответ 3
несколько or
с where
могут быстро усложниться и не уверены в результатах.
Я бы рекомендовал дополнительную скобку плюс использование оператора IN
(NOT IN
в этом случае), например
SELECT * FROM STATUS WHERE (STATE NOT IN ('1', '2')) or STATE is null;
Имплантаты могут различаться между поставщиками баз данных, но приведенный выше синтаксис должен убедиться в результатах.
Ответ 4
Я создал script в исследование Oracle:
create table field_values
(
is_user_deletable VARCHAR2(1 CHAR),
resource_mark VARCHAR2(3 CHAR)
)
insert into field_values values (NULL, NULL);
insert into field_values values ('Y', NULL);
insert into field_values values ('N', NULL);
select * from field_values; -- 3 row
-- 1 row, bad
update field_values set resource_mark = 'D' where is_user_deletable = 'Y';
update field_values set resource_mark = 'D' where is_user_deletable <> 'N';
update field_values set resource_mark = 'D' where is_user_deletable != 'N';
update field_values set resource_mark = 'D' where is_user_deletable not in ('Y');
-- 2 rows, good, but needs more SQL and more comparisons. Does DB optimizes?
update field_values set resource_mark = 'D' where is_user_deletable = 'N' or is_user_deletable is null;
-- it better to have ('Y' and NULL) or ('N' and NULL), but not 'Y' and 'N' and NULL (avoid quires with https://en.wikipedia.org/wiki/Three-valued_logic)
-- adding new column which is 'Y' or 'N' only into existing table may be very long locking operation on existing table (or running long DML script)
Ответ 5
используйте NVL
следующим образом: SELECT * FROM STATUS WHERE NVL(STATE,'X') != '1' AND NVL(STATE,'X')!= '2';