Найкращий спосіб перевірити "порожнє або нульове значення"


176

Який найкращий спосіб перевірити, чи є значення нульовим чи порожнім рядком у операторах Postgres sql?

Значення може бути вираженим довгим, тому бажано, щоб воно було написане лише один раз під контролем.

В даний час я використовую:

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

Але це виглядає трохи некрасиво.

stringexpressionможе бути char(n)стовпцем або виразом, що містить char(n)стовпці з пробілами.

Який найкращий спосіб?


3
Використання charмайже завжди є неправильним вибором через прокладки (і отримані в результаті космічні відходи). Але крім цього: я не думаю, що є кращого рішення.
a_horse_with_no_name

Чому негарна? Логічні та розбірливі.
клин

1
@a_horse_with_no_name: Я думаю, що є.
Ервін Брандстеттер

Відповіді:


283

Вираз 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не є ані NULL, ані порожнім" :

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 | тест1 | тест2 | coalesce1 | coalesce2 | coalesce3
------------------ + ----------- + ------- + ------- + --- -------- + ----------- + -----------
 foo | f | f | f | f | f | f
                  | т | т | т | т | т | т
                  | т | т | т | т | т | т
 нульовий              | нульовий       | т | т | т | т | т

Тест на "нуль або порожній рядок" за допомогою 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 | тест1 | тест2 | coalesce1 | coalesce2 | coalesce3
------------------ + ----------- + ------- + ------- + --- -------- + ----------- + -----------
 foo | f | f | f | f | f | f
                  | т | т | т | т | f | f
                  | f | f | f | f | f | f
 нульовий              | нульовий       | т | т | т | т | f

db <> fiddle тут
Стара квадратна загадка

Пов'язані:


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;

Ви перевірили це на випадок NULL?
Флінш

1
Так. Він не повертає порожні чи нульові рядкові поля.
yglodt

Якщо вам потрібно перевірити лише порожні значення, спробуйте це -> where length(stringexpression) = 0;. Це працює для мене.
Кушань Гунасекера

2

Якщо можуть бути порожні пробіли, можливо, немає кращого рішення. COALESCEє лише для таких проблем, як ваша.


1

Щось я бачив, як люди користуються stringexpression > ''. Це може бути не найшвидшим, але буває одним із найкоротших.

Випробував його як на MS SQL, так і на PostgreSQL.



0

Мій бажаний спосіб порівняти нульові поля: NULLIF (nullablefield,: ParameterValue) NULL AND NULLIF (: ParameterValue, nullablefield) NULL. Це громіздко, але є універсальним для використання, тоді як Coalesce неможливий в деяких випадках.

Друге і зворотне використання NULLIF полягає в тому, що "NULLIF (nullablefield,: ParameterValue) IS NULL" завжди буде повертати "true", якщо перший параметр є нульовим.


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) != '')

Порівняння рядків не потрібно оцінювати, оскільки перша умова хибна.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.