Лучший способ проверить «пустое или нулевое значение»

176

Каков наилучший способ проверить, является ли значение пустым или пустым в выражениях Postgres SQL?

Значение может быть длинным выражением, поэтому предпочтительно, чтобы оно записывалось только один раз при проверке.

В настоящее время я использую:

coalesce( trim(stringexpression),'')=''

Но это выглядит немного некрасиво.

stringexpressionможет быть char(n)столбцом или выражением, содержащим char(n)столбцы с завершающими пробелами.

Какой лучший способ?

Андрус
источник
3
Использование charпочти всегда является неправильным выбором из-за заполнения (и в результате космического мусора). Но кроме этого: я не думаю, что есть лучшее решение.
a_horse_with_no_name
Почему некрасивый? Логично и разборчиво.
Клин
1
@a_horse_with_no_name: я думаю, что есть.
Эрвин Брандштеттер

Ответы:

285

Выражение stringexpression = ''дает:

TRUE   .. для ''(или для любой строки, состоящей только из пробелов с типом данных char(n))
NULL   .. для NULL
FALSE .. для всего остального

Итак, чтобы проверить: « stringexpressionлибо NULL, либо пусто» :

(stringexpression = '') IS NOT FALSE

Или обратный подход (может быть легче читать):

(stringexpression <> '') IS NOT TRUE

Работает для любого типа символов, в том числе char(n). Руководство по сравнению операторов.

Или используйте исходное выражение без trim(), что является дорогостоящим шумом char(n)(см. Ниже) или неверным для других типов символов: строки, состоящие только из пробелов, будут передаваться как пустые строки.

coalesce(stringexpression, '') = ''

Но выражения в верхней части быстрее.

Утверждать обратное еще проще: «не stringexpressionявляется ни пустым, ни пустым» :

stringexpression <> ''

Около char(n)

Речь идет о типе данных char(n), коротко для: character(n). ( char/ characterсокращенно от char(1)/ character(1).) Его использование не рекомендуется в Postgres :

В большинстве ситуаций textили character varyingследует использовать вместо.

Не путать char(n)с типами другой, полезный характер varchar(n), varchar, textили"char" (с двойными кавычками).

В char(n)качестве пустой строки не отличается от любой другой строки , состоящей только из пробелов. Все они складываются в n пробелов в char(n)соответствии с определением типа. Логично следует, что вышеприведенные выражения также работают char(n)- так же, как и эти (что не будет работать для других типов символов):

coalesce(stringexpression, '  ') = '  '
coalesce(stringexpression, '') = '       '

демонстрация

Пустая строка равна любой строке пробелов при приведении к char(n):

SELECT ''::char(5) = ''::char(5)     AS eq1
     , ''::char(5) = '  '::char(5)   AS eq2
     , ''::char(5) = '    '::char(5) AS eq3;

Результат:

 eq1 | eq2 | eq3
 ----+-----+----
 t   | t   | t

Проверка на "нулевую или пустую строку" с char(n):

SELECT stringexpression 
     , stringexpression = ''                   AS base_test
     , (stringexpression = '')  IS NOT FALSE   AS test1
     , (stringexpression <> '') IS NOT TRUE    AS test2
     , coalesce(stringexpression, '') = ''     AS coalesce1
     , coalesce(stringexpression, '  ') = '  ' AS coalesce2
     , coalesce(stringexpression, '') = '  '   AS coalesce3
FROM  (
   VALUES
     ('foo'::char(5))
   , ('')
   , ('   ')                -- not different from '' in char(n)
   , (NULL)
   ) sub(stringexpression);

Результат:

строковое выражение | base_test | test1 | test2 | coalesce1 | coalesce2 | coalesce3
------------------ + ----------- + ------- + ------- + --- -------- + ----------- + -----------
 фу | f | f | f | f | f | е
                  | т | т | т | т | т | T
                  | т | т | т | т | т | T
 ноль              | ноль       | т | т | т | т | T

Проверка на "нулевую или пустую строку" с text:

SELECT stringexpression 
     , stringexpression = ''                   AS base_test
     , (stringexpression = '')  IS NOT FALSE   AS test1
     , (stringexpression <> '') IS NOT TRUE    AS test2
     , coalesce(stringexpression, '') = ''     AS coalesce1
     , coalesce(stringexpression, '  ') = '  ' AS coalesce2
     , coalesce(stringexpression, '') = '  '   AS coalesce3
FROM  (
   VALUES
     ('foo'::text)
   , ('')
   , ('   ')                -- different from '' in a sane character types
   , (NULL)
   ) sub(stringexpression);

Результат:

строковое выражение | base_test | test1 | test2 | coalesce1 | coalesce2 | coalesce3
------------------ + ----------- + ------- + ------- + --- -------- + ----------- + -----------
 фу | f | f | f | f | f | е
                  | т | т | т | т | f | е
                  | f | f | f | f | f | е
 ноль              | ноль       | т | т | т | т | е

db <> скрипеть здесь
Old sqlfiddle

Связанный:

Эрвин Брандштеттер
источник
2
@a_horse_with_no_name: ОП запрашивает best way to check if value is null or empty string. trim()Вызов (сравнительно) дорого - и просто не нужно. Я добавил еще и про char(n)"пустую строку".
Эрвин Брандштеттер
1
Вы написали, что любое строковое выражение, содержащее только пробелы, равно ''. Можно ли снять обшивку и использовать coalesce(stringexpression,'')=''для проверки. Это выглядит более читабельным для меня по сравнению с вашим ответом.
Андрус
1
@Andrus: Да, вы можете. Я добавил это и еще немного к ответу.
Эрвин Брандштеттер,
3
select coalesce(' ', '') = '' возвращает ложь Таким образом, TRIM () требуется
Андрус
1
Но coalesce(' '::char(5), '') = ''нет. В любом случае я бы использовал одно из двух верхних выражений, которые работают для любого типа символов и являются самыми быстрыми и чистыми.
Эрвин Брандштеттер
46

Чтобы проверить на пустое и пустое:

coalesce(string, '') = ''

Для проверки на нулевые, пустые и пробелы (обрезать строку)

coalesce(TRIM(string), '') = ''
Сэм
источник
3
Мне нравится эта простота / ясность этого ответа.
stwr667
12

Проверка длины строки также работает и является компактной:

where length(stringexpression) > 0;
yglodt
источник
Вы проверили это для пустого случая?
Флинш
1
Да, я сделал. Он не возвращает пустых или пустых строковых полей.
Иглодт
Если вам нужно проверить только пустые значения, попробуйте это -> where length(stringexpression) = 0;. Это работает для меня.
Кушан Гунасекера
2

Если могут быть пустые конечные пробелы, возможно, нет лучшего решения. COALESCEтолько для таких проблем, как ваша.

Świstak35
источник
1

То, что я видел, люди используют stringexpression > ''. Это может быть не самым быстрым, но бывает одним из самых коротких.

Пробовал это на MS SQL, а также на PostgreSQL.

TarasB
источник
1

другой способ

nullif(trim(stringExpression),'') is not null
Мовацзем Хосен
источник
1
лучший ответ ИМХО
Джефф
0

Мой предпочтительный способ сравнения пустых полей: NULLIF (nullablefield,: ParameterValue) IS NULL И NULLIF (: ParameterValue, nullablefield) IS NULL. Это громоздко, но универсально, а в некоторых случаях объединить невозможно.

Второе и обратное использование NULLIF заключается в том, что «NULLIF (nullablefield,: ParameterValue) IS NULL» всегда будет возвращать «true», если первый параметр имеет значение null.

Данило да Силва
источник
0

Если база данных имеет большое количество записей, то это null checkможет занять больше времени, вы можете использовать нулевую проверку различными способами, такими как: 1) where columnname is null 2) where not exists() 3)WHERE (case when columnname is null then true end)

Амбриш Раджпут
источник
0

Многие ответы - самый короткий, не обязательно лучший, если в столбце много нулей. Прерывание проверок позволяет оптимизатору оценивать проверку быстрее, поскольку ему не нужно выполнять работу с другим условием.

(stringexpression IS NOT NULL AND trim(stringexpression) != '')

Сравнение строк не нужно оценивать, поскольку первое условие ложно.

Джон В.Е.
источник