I have a column in a table which might contain null or empty values. How do I check if a column is empty or null in the rows present in a table?
(e.g. null or '' or ' ' or ' ' and ...)
asked Dec 12, 2011 at 6:49
3
This will select all rows where some_col
is NULL
or ''
(empty string)
SELECT * FROM table WHERE some_col IS NULL OR some_col = '';
answered Dec 12, 2011 at 6:54
mačekmaček
75.9k37 gold badges167 silver badges197 bronze badges
2
As defined by the SQL-92 Standard, when comparing two strings of differing widths, the narrower value is right-padded with spaces to make it is same width as the wider value. Therefore, all string values that consist entirely of spaces (including zero spaces) will be deemed to be equal e.g.
'' = ' ' IS TRUE
'' = ' ' IS TRUE
' ' = ' ' IS TRUE
' ' = ' ' IS TRUE
etc
Therefore, this should work regardless of how many spaces make up the some_col
value:
SELECT *
FROM T
WHERE some_col IS NULL
OR some_col = ' ';
or more succinctly:
SELECT *
FROM T
WHERE NULLIF(some_col, ' ') IS NULL;
answered Dec 12, 2011 at 12:28
onedaywhenonedaywhen
54.9k12 gold badges99 silver badges138 bronze badges
3
A shorter way to write the condition:
WHERE some_col > ''
Since null > ''
produces unknown
, this has the effect of filtering out both null
and empty strings.
answered Jun 30, 2013 at 16:24
AndomarAndomar
231k49 gold badges377 silver badges402 bronze badges
6
Please mind: the best practice it at the end of the answer.
You can test whether a column is null or is not null using WHERE col IS NULL
or WHERE col IS NOT NULL
e.g.
SELECT myCol
FROM MyTable
WHERE MyCol IS NULL
In your example you have various permutations of white space. You can strip white space using TRIM
and you can use COALESCE
to default a NULL value (COALESCE will return the first non-null value from the values you suppy.
e.g.
SELECT myCol
FROM MyTable
WHERE TRIM(COALESCE(MyCol, '')) = ''
This final query will return rows where MyCol
is null or is any length of whitespace.
If you can avoid it, it’s better not to have a function on a column in the WHERE clause as it makes it difficult to use an index. If you simply want to check if a column is null or empty, you may be better off doing this:
SELECT myCol
FROM MyTable
WHERE MyCol IS NULL OR MyCol = ''
See TRIM COALESCE and IS NULL for more info.
Also Working with null values from the MySQL docs
questionto42
6,5464 gold badges52 silver badges85 bronze badges
answered Dec 12, 2011 at 6:52
Code MagicianCode Magician
23.1k7 gold badges59 silver badges77 bronze badges
2
Another method without WHERE, try this..
Will select both Empty and NULL values
SELECT ISNULL(NULLIF(fieldname,'')) FROM tablename
answered Jan 3, 2016 at 17:06
PodTech.ioPodTech.io
4,77640 silver badges24 bronze badges
2
Either
SELECT IF(field1 IS NULL or field1 = '', 'empty', field1) as field1 from tablename
or
SELECT case when field1 IS NULL or field1 = ''
then 'empty'
else field1
end as field1 from tablename
answered Jun 7, 2017 at 3:48
This statement is much cleaner and more readable for me:
select * from my_table where ISNULL(NULLIF(some_col, ''));
answered May 30, 2016 at 16:10
AmaynutAmaynut
4,0215 gold badges39 silver badges43 bronze badges
try
SELECT 0 IS NULL , '' IS NULL , NULL IS NULL
-> 0, 0, 1
or
SELECT ISNULL(' ') , ISNULL( NULL )
-> 0 ,1
Reference
answered Dec 12, 2011 at 6:53
xkeshavxkeshav
53.4k43 gold badges175 silver badges245 bronze badges
I hate messy fields in my databases. If the column might be a blank string or null, I’d rather fix this before doing the select each time, like this:
UPDATE MyTable SET MyColumn=NULL WHERE MyColumn='';
SELECT * FROM MyTable WHERE MyColumn IS NULL
This keeps the data tidy, as long as you don’t specifically need to differentiate between NULL and empty for some reason.
answered Dec 3, 2014 at 17:16
1
While checking null or Empty
value for a column in my project, I noticed that there are some support concern in various Databases.
Every Database doesn’t support TRIM
method.
Below is the matrix just to understand the supported methods by different databases.
The TRIM function in SQL is used to remove specified prefix or suffix from a string. The most common pattern being removed is white spaces. This function is called differently in different databases:
- MySQL:
TRIM(), RTRIM(), LTRIM()
- Oracle:
RTRIM(), LTRIM()
- SQL Server:
RTRIM(), LTRIM()
How to Check Empty/Null :-
Below are two different ways according to different Databases-
The syntax for these trim functions are:
-
Use of Trim to check-
SELECT FirstName FROM UserDetails WHERE TRIM(LastName) IS NULL
-
Use of LTRIM & RTRIM to check-
SELECT FirstName FROM UserDetails WHERE LTRIM(RTRIM(LastName)) IS NULL
Above both ways provide same result just use based on your DataBase support. It Just returns the FirstName
from UserDetails
table if it has an empty LastName
Hoping this will help you
answered Oct 21, 2016 at 20:58
Vikash PandeyVikash Pandey
5,4016 gold badges39 silver badges42 bronze badges
SELECT * FROM tbl WHERE trim(IFNULL(col,'')) <> '';
Paul Roub
36.3k27 gold badges83 silver badges92 bronze badges
answered Feb 12, 2019 at 15:47
3
My two cents.
In MySQL you can use the COALESCE
function:
Returns the first non-NULL value in the list, or NULL if there are no non-NULL values.
So you can simplify your query like this:
SELECT * FROM table WHERE COALESCE(some_col, '') = '';
answered Sep 8, 2021 at 9:54
PiozPioz
5,9613 gold badges46 silver badges65 bronze badges
If you want to have NULL values presented last when doing an ORDER BY, try this:
SELECT * FROM my_table WHERE NULLIF(some_col, '') IS NULL;
answered Dec 12, 2011 at 6:52
GhostmanGhostman
6,0229 gold badges34 silver badges53 bronze badges
0
You can also do
SELECT * FROM table WHERE column_name LIKE ''
The inverse being
SELECT * FROM table WHERE column_name NOT LIKE ''
answered Jun 22, 2017 at 3:18
brenjtbrenjt
16k13 gold badges77 silver badges118 bronze badges
2
select * from table where length(RTRIM(LTRIM(column_name))) > 0
answered Jan 25, 2019 at 13:15
Hakan IlgarHakan Ilgar
1415 silver badges14 bronze badges
2
The below SQL query works fine.
SELECT * FROM <table-name> WHERE <column-name> IS NULL;
answered Mar 23, 2022 at 13:55
1
In my case, space was entered in the column during the data import and though it looked like an empty column its length was 1. So first of all I checked the length of the empty looking column using length(column)
then based on this we can write search query
SELECT * FROM table WHERE LENGTH(column)=0;
Hashim Aziz
3,7885 gold badges35 silver badges66 bronze badges
answered Feb 20, 2019 at 15:46
MR ANDMR AND
3767 silver badges27 bronze badges
3
Below code works great, to check null or empty
and fallback
to other column:
SELECT COALESCE(NULLIF(col1, ''), col2) as 'someName'
Above sql means:
if `col1` column value is NOT null and NOT empty string
then take `col1`
otherwise take `col2`
return above value as `someName`
answered Mar 14 at 3:52
try this if the datatype are string and row is null
SELECT * FROM table WHERE column_name IS NULL OR column_name = ''
if the datatype are int or column are 0 then try this
SELECT * FROM table WHERE column_name > = 0
answered Mar 31, 2017 at 3:00
Get rows with NULL, 0, », ‘ ‘, ‘ ‘
SELECT * FROM table WHERE some_col IS NOT TRUE;
Get rows without NULL, 0, », ‘ ‘, ‘ ‘
SELECT * FROM table WHERE some_col IS TRUE;
answered Sep 23, 2020 at 19:41
ArthurArthur
1172 bronze badges
1
SELECT column_name FROM table_name WHERE column_name IN (NULL, '')
Nathan Tuggy
2,24327 gold badges30 silver badges38 bronze badges
answered Jun 7, 2017 at 2:59
2
How do you write a SELECT statement that only returns rows where the value for a certain column is null?
Annabelle
10.6k5 gold badges26 silver badges26 bronze badges
asked Jul 30, 2010 at 6:08
2
Do you mean something like:
SELECT COLUMN1, COLUMN2 FROM MY_TABLE WHERE COLUMN1 = 'Value' OR COLUMN1 IS NULL
?
answered Jul 30, 2010 at 6:11
Jon SkeetJon Skeet
1.4m859 gold badges9095 silver badges9169 bronze badges
0
I’m not sure if this answers your question, but using the IS NULL construct, you can test whether any given scalar expression is NULL:
SELECT * FROM customers WHERE first_name IS NULL
On MS SQL Server, the ISNULL() function returns the first argument if it’s not NULL, otherwise it returns the second. You can effectively use this to make sure a query always yields a value instead of NULL, e.g.:
SELECT ISNULL(column1, 'No value found') FROM mytable WHERE column2 = 23
Other DBMSes have similar functionality available.
If you want to know whether a column can be null (i.e., is defined to be nullable), without querying for actual data, you should look into information_schema.
answered Jul 30, 2010 at 6:16
tdammerstdammers
20.3k1 gold badge38 silver badges56 bronze badges
0
Use Is Null
select * from tblName where clmnName is null
answered Jul 30, 2010 at 6:10
anishMarokeyanishMarokey
11.2k2 gold badges33 silver badges47 bronze badges
You want to know if the column is null
select * from foo where bar is null
If you want to check for some value not equal to something and the column also contains null values you will not get the columns with null in it
does not work:
select * from foo where bar <> 'value'
does work:
select * from foo where bar <> 'value' or bar is null
in Oracle (don’t know on other DBMS) some people use this
select * from foo where NVL(bar,'n/a') <> 'value'
if I read the answer from tdammers correctly then in MS SQL Server this is like that
select * from foo where ISNULL(bar,'n/a') <> 'value'
in my opinion it is a bit of a hack and the moment ‘value’ becomes a variable the statement tends to become buggy if the variable contains ‘n/a’.
answered Jul 30, 2010 at 8:03
holhol
8,2355 gold badges32 silver badges59 bronze badges
select Column from Table where Column is null;
answered Nov 4, 2015 at 8:22
Taras MelnykTaras Melnyk
3,0173 gold badges38 silver badges34 bronze badges
1
select * from tableName where columnName is null
answered Nov 15, 2015 at 6:31
For some reasons IS NULL
may not work with some column data type. I was in need to get all the employees that their English full name is missing, I’ve used:
SELECT emp_id, Full_Name_Ar, Full_Name_En
FROM employees
WHERE Full_Name_En = '' or Full_Name_En is null
answered Apr 29, 2014 at 17:41
MAKMAK
3793 silver badges7 bronze badges
1
SELECT NULL-значение
Достаточно часто встречаются такие случаи, когда в таблице имеются записи с не заданными значениями какого-либо из полей, потому что значение поля неизвестно или его просто нет. В таких случаях SQL позволяет указать в поле NULL-значение. Строго говоря, NULL-значение вовсе не представлено в поле. Когда значение поля есть NULL — это значит, что программа базы данных специальным образом помечает поле, как не содержащее какого-либо значения для данной строки (записи).
Дело обстоит не так в случае простого приписывания полю значения «нуль» или «пробел», которые база данных трактует как любое другое значение. Поскольку NULL не является значением как таковым, он не имеет типа данных. NULL может размещаться в поле любого типа. Тем не менее, NULL, как NULL-значение, часто используется в SQL.
Предположим, появился покупатель, которому еще не назначен продавец. Чтобы констатировать этот факт, нужно ввести значение NULL в поле snum, а реальное значение включить туда позже, когда данному покупателю будет назначен продавец.
SQL IS NULL
Поскольку NULL фиксирует пропущенные значения, результат любого сравнения при наличии NULL-значений неизвестен. Когда NULL-значение сравнивается с любым значением, даже с NULL-значением, результат просто неизвестен. Булево значение «неизвестно» ведет себя также, как «ложь» — строка, на которой предикат принимает значение «неизвестно», не включается в результат запроса – при одном важном исключении: NOT от лжи есть истина (NOT (false)=true), тогда как NOT от неизвестного значения есть также неизвестное значение. Следовательно, такое выражение как «city = NULL» или «city IN (NULL)» является неизвестным независимо от значения city.
Часто необходимо различать false и unknown – строки, содержащие значения столбца, не удовлетворяющие предикату, и строки, которые содержат NULL. Для этой цели SQL располагает специальным оператором IS, который используется с ключевым словом NULL для локализации NULL-значения. SQL IS NULL. Пример. Вывести все поля из талицы Customers, значения поля city которых равны NULL:
SELECT * FROM Customers WHERE city IS NULL
В данном случае выходных данных не будет, поскольку в поле city нет NULL-значений.
SQL IS NOT NULL
Условие IS NOT NULL используется в запросах для выборки записей со значениями не равных значению NULL SQL IS NOT NULL. Пример. Вывести все поля из талицы Customers, значения поля city которых НЕ равны NULL:
SELECT * FROM Customers WHERE city IS NOT NULL
Время на прочтение
10 мин
Количество просмотров 173K
Всем привет!
Долго думал, что бы написать полезного про Оракл, перепробовал кучу тем. Каждый раз получалось слишком длинно, потому что уносило глубоко в дебри. Поэтому решил начать с максимально простой темы, чтобы оценить интерес аудитории и её отношение к моему стилю изложения материала (имхо, писатель из меня не очень). Несколько замечаний:
- заметка относится к СУБД Oracle, но большинство написанного касается и других СУБД;
- не получилось симпатично оформть код: тег source lang=«sql» подсвечивает слишком мало, как сделать по другому не в курсе. Если кто покажет, быстро всё приведу в более читабельный вид.
Итак.
Основные положения
Специальное значение NULL означает отсутствие данных, констатацию того факта, что значение неизвестно. По умолчанию это значение могут принимать столбцы и переменные любых типов, если только на них не наложено ограничение NOT NULL
. Также, СУБД автоматически добавляет ограничение NOT NULL
к столбцам, включенным в первичный ключ таблицы.
Основная особенность NULLа заключается в том, что он не равен ничему, даже другому NULLу. С ним нельзя сравнить какое-либо значение с помощью любых операторов: =
, <
, >
, like
… Даже выражение NULL != NULL
не будет истинным, ведь нельзя однозначно сравнить одну неизвестность с другой. Кстати, ложным это выражение тоже не будет, потому что при вычислении условий Oracle не ограничивается состояниями ИСТИНА
и ЛОЖЬ
. Из-за наличия элемента неопределённости в виде NULLа существует ещё одно состояние — НЕИЗВЕСТНО
.
Таким образом, Oracle оперирует не двухзначной, а трёхзначной логикой. Эту особенность заложил в свою реляционную теорию дедушка Кодд, а Oracle, являясь реляционной СУБД, полностью следует его заветам. Чтобы не медитировать над “странными” результатами запросов, разработчику необходимо знать таблицу истинности трёхзначной логики. Ознакомиться с ней можно, например, на английской википедии: Three-valued_logic.
Для удобства сделаем процедуру, печатающую состояние булевого параметра:
create procedure test_bool( p_bool boolean ) is
begin
case when p_bool = true then dbms_output.put_line('TRUE');
when p_bool = false then dbms_output.put_line('FALSE');
else dbms_output.put_line('UNKNOWN');
end case;
end test_bool;
и включим опцию печати сообщений на консоль:
set serveroutput on
Привычные операторы сравнения пасуют перед NULLом:
exec test_bool( null = null ); -- UNKNOWN
exec test_bool( null != null ); -- UNKNOWN
exec test_bool( null = 'a' ); -- UNKNOWN
exec test_bool( null != 'a' ); -- UNKNOWN
Сравнение с NULLом
Существуют специальные операторы IS NULL
и IS NOT NULL
, которые позволяют производить сравнения с NULLами. IS NULL
вернёт истину, если операнд имеет значение NULL
и ложь, если он им не является.
select case when null is null then 'YES' else 'NO' end from dual; -- YES
select case when 'a' is null then 'YES' else 'NO' end from dual; -- NO
Соответственно, IS NOT NULL
действует наоборот: вернёт истину, если значение операнда отлично от NULLа и ложь, если он является NULLом:
select case when 'a' is NOT null then 'YES' else 'NO' end from dual; -- YES
select case when null is NOT null then 'YES' else 'NO' end from dual; -- NO
Кроме того, есть пара исключений из правил, касающихся сравнений с отсутствующими значениями. Во-первых, — это функция DECODE
, которая считает два NULLа эквивалентными друг другу. Во-вторых, — это составные индексы: если два ключа содержат пустые поля, но все их непустые поля равны, то Oracle считает эти два ключа эквивалентными.
DECODE
идёт против системы:
select decode( null
, 1, 'ONE'
, null, 'EMPTY' -- это условие будет истинным
, 'DEFAULT'
)
from dual;
Пример с составными индексами находится в параграфе про индексы.
Логические операции и NULL
Обычно, состояние НЕИЗВЕСТНО
обрабатывается так же, как ЛОЖЬ
. Например, если вы выбираете строки из таблицы и вычисление условия x = NULL
в предложении WHERE
дало результат НЕИЗВЕСТНО
, то вы не получите ни одной строки. Однако, есть и отличие: если выражение НЕ(ЛОЖЬ)
вернёт истину, то НЕ(НЕИЗВЕСТНО)
вернёт НЕИЗВЕСТНО
. Логические операторы AND
и OR
также имеют свои особенности при обработке неизвестного состояния. Конкретика в примере ниже.
В большинстве случаев неизвестный результат обрабатывается как ЛОЖЬ
:
select 1 from dual where dummy = null; -- запрос не вернёт записей
Отрицание неизвестности даёт неизвестность:
exec test_bool( not(null = null) ); -- UNKNOWN
exec test_bool( not(null != null) ); -- UNKNOWN
exec test_bool( not(null = 'a') ); -- UNKNOWN
exec test_bool( not(null != 'a') ); -- UNKNOWN
Оператор OR
:
exec test_bool( null or true ); -- TRUE <- !!!!!
exec test_bool( null or false ); -- UNKNOWN
exec test_bool( null or null ); -- UNKNOWN
Оператор AND
:
exec test_bool( null and true ); -- UNKNOWN
exec test_bool( null and false ); -- FALSE <- !!!!!
exec test_bool( null and null ); -- UNKNOWN
Операторы IN и NOT IN
Для начала сделаем несколько предварительных действий. Для тестов создадим таблицу T
с одним числовым столбцом A
и четырьмя строками: 1, 2, 3
и NULL
create table t as select column_value a from table(sys.odcinumberlist(1,2,3,null));
Включим трассировку запроса (для этого надо обладать ролью PLUSTRACE
).
В листингах от трассировки оставлена только часть filter, чтобы показать, во что разворачиваются указанные в запросе условия.
set autotrace on
Предварительные действия закончены, давайте теперь поработаем с операторами. Попробуем выбрать все записи, которые входят в набор (1, 2, NULL)
:
select * from t where a in(1,2,null); -- вернёт [1,2]
-- Predicate Information:
-- filter("A"=1 OR "A"=2 OR "A"=TO_NUMBER(NULL))
Как видим, строка с NULLом не выбралась. Произошло это из-за того, что вычисление предиката "A"=TO_NUMBER(NULL)
вернуло состояние НЕИЗВЕСТНО
. Для того, чтобы включить NULLы в результат запроса, придётся указать это явно:
select * from t where a in(1,2) or a is null; -- вернёт [1,2,NULL]
-- Predicate Information:
-- filter("A" IS NULL OR "A"=1 OR "A"=2)
Попробуем теперь с NOT IN
:
select * from t where a not in(1,2,null); -- no rows selected
-- Predicate Information:
-- filter("A"<>1 AND "A"<>2 AND "A"<>TO_NUMBER(NULL))
Вообще ни одной записи! Давайте разберёмся, почему тройка не попала в результаты запроса. Посчитаем вручную фильтр, который применила СУБД, для случая A=3
:
3<>1 AND 3<>2 AND 3<>to_number(NULL) / / / true AND true AND unknown / / true AND unknown / unknown
Из-за особенностей трёхзначной логики NOT IN
вообще не дружит с NULLами: как только NULL попал в условия отбора, данных не ждите.
NULL и пустая строка
Здесь Oracle отходит от стандарта ANSI SQL и провозглашает эквивалентность NULLа и пустой строки. Это, пожалуй, одна из наиболее спорных фич, которая время от времени рождает многостраничные обсуждения с переходом на личности, поливанием друг друга фекалиями и прочими непременными атрибутами жёстких споров. Судя по документации, Oracle и сам бы не прочь изменить эту ситуацию (там сказано, что хоть сейчас пустая строка и обрабатывается как NULL, в будущих релизах это может измениться), но на сегодняшний день под эту СУБД написано такое колоссальное количество кода, что взять и поменять поведение системы вряд ли реально. Тем более, говорить об этом они начали как минимум с седьмой версии СУБД (1992-1996 годы), а сейчас уже двенадцатая на подходе.
NULL и пустая строка эквивалентны:
exec test_bool( '' is null ); -- TRUE
непременный атрибут жёсткого спора:
select count(*) comments_count, avg(c.vote) avg_vote
from habr.comments c join habr.posts p on( c.post_id = p.id )
where lower(p.title) like '%пробел%'
and lower(p.title) like '%табуляци%';
COMMENTS_COUNT AVG_VOTE
--------------- ---------
100500 -100
Если последовать завету классика и посмотреть в корень, то причину эквивалентности пуcтой строки и NULLа можно найти в формате хранения varchar`ов и NULLов внутри блоков данных. Oracle хранит строки таблицы в структуре, состоящей из заголовка, за которым следуют столбцы данных. Каждый столбец представлен двумя полями: длина данных в столбце (1 или 3 байта) и, собственно, сами данные. Если varchar2
имеет нулевую длину, то в поле с данными писать нечего, оно не занимает ни байта, а в поле с длиной записывается специальное значение 0xFF
, обозначающее отсутствие данных. NULL представлен точно так же: поле с данными отсутствует, а в поле с длиной записывается 0xFF
. Разработчики Оракла могли бы, конечно, разделить эти два состояния, но так уж издревле у них повелось.
Лично мне эквивалентность пустой строки и NULLа кажется вполне естественной и логичной. Само название «пустая строка» подразумавает отсутствие значения, пустоту, дырку от бублика. NULL, в общем-то, обозначает то же самое. Но здесь есть неприятное следствие: если про пустую строку можно с уверенностью сказать, что её длина равна нулю, то длина NULLа никак не определена. Поэтому, выражение length('')
вернёт вам NULL, а не ноль, как вы, очевидно, ожидали. Ещё одна проблема: нельзя сравнивать с пустой строкой. Выражение val = ''
вернёт состояние НЕИЗВЕСТНО
, так как, по сути, эквивалентно val = NULL
.
Длина пустой строки не определена:
select length('') from dual; -- NULL
Сравнение с пустой строкой невозможно:
exec test_bool( 'a' != '' ); -- UNKNOWN
Критики подхода, предлагаемого Ораклом, говорят о том, что пустая строка не обязательно обозначает неизвестность. Например, менеджер по продажам заполняет карточку клиента. Он может указать его контактный телефон (555-123456), может указать, что он неизвестен (NULL), а может и указать, что контактный телефон отсутствует (пустая строка). С оракловым способом хранения пустых строк реализовать последний вариант будет проблемно. С точки зрения семантики довод правильный, но у меня на него всегда возникает вопрос, полного ответа на который я так и не получил: как менеджер введёт в поле «телефон» пустую строку и как он в дальнейшем отличит его от NULLа? Варианты, конечно, есть, но всё-таки…
Вообще-то, если говорить про PL/SQL, то где-то глубоко внутри его движка пустая строка и NULL различаются. Один из способов увидеть это связан с тем, что ассоциативные коллекции позволяют сохранить элемент с индексом ''
(пустая строка), но не позволяют сохранить элемент с индексом NULL:
declare
procedure empty_or_null( p_val varchar2 ) is
type tt is table of varchar2(1) index by varchar2(10);
t tt;
begin
if p_val is not null then
dbms_output.put_line('не пусто');
else
-- пытаемся создать элемент с индексом p_val
t(p_val) := 'x';
-- получилось! Значит, пустая строка
dbms_output.put_line('пустая строка');
end if;
exception
-- создать элемент с индексом p_val не получилось. Значит, NULL
when others then dbms_output.put_line('NULL');
end;
begin
empty_or_null( 'qwe' ); -- не пусто
empty_or_null( '' ); -- пустая строка
empty_or_null( NULL ); -- NULL
end;
Использовать такие финты ушами на практике не стоит. Во избежание проблем лучше усвоить правило из доки: пустая строка и NULL в оракле неразличимы.
Математика NULLа
Этот маленький абзац писался пятничным вечером под пиво, на фоне пятничного РЕН-ТВшного фильма. Переписывать его лень, уж извините.
Задача. У Маши до замужества с Колей было неизвестное количество любовников. Коля знает, что после замужества у Маши был секс с ним, Сашей и Витей. Помогите найти Коле точное количество любовников Маши.
Очевидно, что мы ничем не сможем помочь Коле: неизвестное количество любовников Маши до замужества сводит все расчёты к одному значению — неизвестно. Oracle, хоть и назвался оракулом, в этом вопросе уходит не дальше, чем участники битвы экстрасенсов: он даёт очевидные ответы только на очевидные вопросы. Хотя, надо признать, что Oracle гораздо честнее: в случае с Колей он не будет заниматься психоанализом и сразу скажет: «я не знаю»:
select decode( null + 10, null, 'неизвестно', 'известно') a from dual; -- неизвестно
select decode( null * 10, null, 'неизвестно', 'известно') a from dual; -- неизвестно
select decode( abs(null), null, 'неизвестно', 'известно') a from dual; -- неизвестно
select decode( sign(null), null, 'неизвестно', 'известно') a from dual; -- неизвестно
С конкатенацией дела обстоят по другому: вы можете добавить NULL к строке и это её не изменит. Такая вот политика двойных стандартов.
select null ||'AA'|| null ||'BB'|| null from dual; -- AABB
NULL и агрегатные функции
Почти все агрегатные функции, за исключением COUNT
(и то не всегда), игнорируют пустые значения при расчётах. Если бы они этого не делали, то первый же залетевший NULL привёл бы результат функции к неизвестному значению. Возьмём для примера функцию SUM
, которой необходимо просуммировать ряд (1, 3, null, 2)
. Если бы она учитывала пустые значения, то мы бы получили такую последовательность действий:
1 + 3 = 4; 4 + null = null; null + 2 = null
.
Вряд ли вас устроит такой расчёт при вычислении агрегатов, ведь вы наверняка не это хотели получить. А какой бы был геморрой с построением хранилищ данных… Бррррр…
Таблица с данными. Используется ниже много раз:
create table agg( id int, n int );
insert into agg values( 1, 1 );
insert into agg values( 2, 3 );
insert into agg values( 3, null );
insert into agg values( 4, 2 );
commit;
Пустые значения игнорируются агрегатами:
select sum(n) from agg; -- 6
Функция подсчёта количества строк COUNT
, если используется в виде COUNT(*)
или COUNT(константа)
, будет учитывать пустые значения. Однако, если она используется в виде COUNT(выражение)
, то пустые значения будут игнорироваться.
с константой:
select count(*) from agg; -- 4
select count(1+1) from agg; -- 4
select count(user) from agg; -- 4
С выражением:
select count(n) from agg; -- 3
select count(id) from agg; -- 4
select count(abs(n)) from agg; -- 3
Также, следует быть осторожным с функциями вроде AVG
. Поскольку она проигнорирует пустые значения, результат по полю N
будет равен (1+3+2)/3
, а не (1+3+2)/4
. Возможно, такой расчёт среднего вам не нужен. Для решения подобных проблем есть стандартное решение — воспользоваться функцией NVL
:
select avg(n) from agg; -- (1 + 3 + 2) / 3 = 2
select avg(nvl(n,0)) from agg; -- (1 + 3 + 0 + 2) / 4 = 1.5
Агрегатные функции возвращают состояние НЕИЗВЕСТНО
, если они применяются к пустому набору данных, либо если он состоит только из NULLов. Исключение составляют предназначенные для подсчёта количества строк функции REGR_COUNT
и COUNT(выражение)
. Они в перечисленных выше случаях вернут ноль.
Набор данных только из NULLов:
select sum(n) from agg where n is null; -- НЕИЗВЕСТНО
select avg(n) from agg where n is null; -- НЕИЗВЕСТНО
select regr_count(n,n) from agg where n is null; -- 0
select count(n) from agg where n is null; -- 0
Пустой набор данных:
select sum(n) from agg where 1 = 0; -- НЕИЗВЕСТНО
select avg(n) from agg where 1 = 0; -- НЕИЗВЕСТНО
select regr_count(n,n) from agg where 1 = 0; -- 0
select count(n) from agg where 1 = 0; -- 0
NULL в OLAP
Очень коротко ещё об одной особенности, связанной с агрегатами. В многомерных кубах NULL в результах запроса может означать как отсутствие данных, так и признак группировки по измерению. Самое противное, что на глаз эти две его ипостаси никак не различишь. К счастью, есть специальные функции GROUPING
и GROUPING_ID
, у которых глаз острее. GROUPING(столбец)
вернёт единицу, если NULL в столбце измерения означает признак группировки по этому столбцу и ноль, если там содержится конкретное значение (в частности, NULL). Функция GROUPING_ID
— это битовый вектор из GROUPING
ов, в этой заметке она точно лишняя.
В общем, такая вот краткая и сумбурная информация про дуализм NULLа в многомерном анализе. Ниже пример использования GROUPING
, а за подробностями велкам ту Data Warehousing Guide, глава 21.
Удобная фишка sqlplus: при выводе данных заменяет NULL на указанную строку:
set null [NULL]
Проверяем дуализм NULLа в многомерном кубе:
with t as (
-- Иван купил 1 кефир
select 'IVAN' customer, 'KEFIR' product, 1 qty from dual union all
-- неизвестный покупатель купил 2 молока
select NULL customer, 'MOLOKO' product, 2 qty from dual union all
-- Иван купил 2 молока
select 'IVAN' customer, 'MOLOKO' product, 2 qty from dual
)
select customer cust, grouping(customer) grp_c
, product prod, grouping(product) grp_p
, sum(qty) qty
from t
group by cube(customer, product)
order by grp_c, grp_p;
CUST GRP_C PROD GRP_P QTY
---- ----- ------ ----- ----
[NULL] 0 MOLOKO 0 2 -- безымянный клиент купил 2 упаковки молока
IVAN 0 KEFIR 0 1 -- Иван купил 1 упаковку кефира
IVAN 0 MOLOKO 0 2 -- Иван купил 2 упаковки молока
IVAN 0 [NULL] 1 3 -- Иван купил 3 упаковки всех товаров
[NULL] 0 [NULL] 1 2 -- безымянный клиент купил 2 упаковки всех товаров
[NULL] 1 MOLOKO 0 4 -- все клиенты купили 4 упаковки молока
[NULL] 1 KEFIR 0 1 -- все клиенты купили 1 упаковку кефира
[NULL] 1 [NULL] 1 5 -- все клиенты купили 5 упаковок всех товаров
Что осталось за кадром
Получилось довольно длинно, поэтому часть информации пришлось вырезать. А именно:
- NULL в индексах (обычные, составные, бинарные, функциональные). Там у меня больше листингов, чем текста;
- разбор функций для работы с NULLами: документированных и не очень;
- работа с NULLами в запросах (всяческие кейсы)
- может, ещё какие-то моменты забыл упомянуть, пишите в комментарии, добавлю.
Критика, дополнения и намёки на некомпетентность автора (с отсылкой в доку) приветствуются. Собственно, для этого всё и затевалось.
In SQL Where clause tutorial, we learned how to use comparison operators such as =, <, > etc in where clause for conditions. However when a column (field) of table has null values then such operators do not work on those columns, in such case we have to use IS NULL & IS NOT NULL operators for the null check. In this guide, we will learn how to deal with null values in SQL.
How to check for null values in SQL
We cannot use comparison operators such as =, <, > etc on null values because the result is undefined. To check for null values we can use IS NULL and IS NOT NULL operators. Lets see the syntax of these operators.
IS NULL Syntax
Null check:
SELECT column_name1, column_name2, column_name3, ... FROM table_name WHERE column_nameN IS NULL;
IS NOT NULL Syntax
Not Null check:
SELECT column_name1, column_name2, column_name3, ... FROM table_name WHERE column_nameN IS NOT NULL;
SQL IS NULL or empty check Example
Table: Employees
EmployeeName EmployeeAge EmployeePhoneNo EmployeeAddress ------------ ----------- --------------- --------------- Cindi 34 95XXXXXXX8 Noida Linda 35 Agra Shaun 33 75XXXXXXX4 Delhi Timmy 34 Noida Pappu 36 Noida
The following SQL statement will fetch the EmployeeName & EmployeeAddress details of employees where the EmployeePhoneNo column has null value.
SELECT EmployeeName, EmployeeAddress FROM Employees WHERE EmployeePhoneNo IS NULL;
Result:
EmployeeName EmployeeAddress ------------ --------------- Linda Agra Timmy Noida Pappu Noida
SQL IS NOT NULL in where clause Example
Lets take the same example that we have seen above. In this example, we will check for the not null values.
Table: Employees
EmployeeName EmployeeAge EmployeePhoneNo EmployeeAddress ------------ ----------- --------------- --------------- Cindi 34 95XXXXXXX8 Noida Linda 35 Agra Shaun 33 75XXXXXXX4 Delhi Timmy 34 Noida Pappu 36 Noida
The following SQL statement will fetch the EmployeeName & EmployeeAddress details of employees where the value of EmployeePhoneNo column is not null.
SELECT EmployeeName, EmployeeAddress FROM Employees WHERE EmployeePhoneNo IS NOT NULL;
Result:
EmployeeName EmployeeAddress ------------ --------------- Cindi Noida Shaun Delhi