Как найти null в таблице sql

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 ...)

Peter Mortensen's user avatar

asked Dec 12, 2011 at 6:49

priya's user avatar

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ček's user avatar

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

onedaywhen's user avatar

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

Andomar's user avatar

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's user avatar

questionto42

6,5464 gold badges52 silver badges85 bronze badges

answered Dec 12, 2011 at 6:52

Code Magician's user avatar

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.io's user avatar

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

Reynante Daitol's user avatar

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

Amaynut's user avatar

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

xkeshav's user avatar

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

Keith Johnson's user avatar

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:

  1. Use of Trim to check-

    SELECT FirstName FROM UserDetails WHERE TRIM(LastName) IS NULL

  2. 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 Pandey's user avatar

Vikash PandeyVikash Pandey

5,4016 gold badges39 silver badges42 bronze badges

SELECT * FROM tbl WHERE trim(IFNULL(col,'')) <> '';

Paul Roub's user avatar

Paul Roub

36.3k27 gold badges83 silver badges92 bronze badges

answered Feb 12, 2019 at 15:47

Baltazar Moreno's user avatar

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

Pioz's user avatar

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

Ghostman's user avatar

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

brenjt's user avatar

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 Ilgar's user avatar

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

Kalhara Tennakoon's user avatar

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's user avatar

Hashim Aziz

3,7885 gold badges35 silver badges66 bronze badges

answered Feb 20, 2019 at 15:46

MR AND's user avatar

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

Manohar Reddy Poreddy's user avatar

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

HoldOffHunger's user avatar

answered Mar 31, 2017 at 3:00

Monis Qureshi's user avatar

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

Arthur's user avatar

ArthurArthur

1172 bronze badges

1

SELECT column_name FROM table_name WHERE column_name IN (NULL, '')

Nathan Tuggy's user avatar

Nathan Tuggy

2,24327 gold badges30 silver badges38 bronze badges

answered Jun 7, 2017 at 2:59

SaAy's user avatar

2

How do you write a SELECT statement that only returns rows where the value for a certain column is null?

Annabelle's user avatar

Annabelle

10.6k5 gold badges26 silver badges26 bronze badges

asked Jul 30, 2010 at 6:08

anjum's user avatar

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 Skeet's user avatar

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

tdammers's user avatar

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

anishMarokey's user avatar

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

hol's user avatar

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 Melnyk's user avatar

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

Md.Aminul Islam's user avatar

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

MAK's user avatar

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

Понравилась статья? Поделить с друзьями:

Не пропустите также:

  • Unsupported graphics card detected a gpu with support for d3d как исправить
  • Как найти второй угол преломления
  • Как найти периметр правило для 3 класса
  • Как составить прайс лист на работы
  • Алгоритм как составить план текста

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии