Najlepszy sposób na sprawdzenie „wartości pustej lub zerowej”

176

Jaki jest najlepszy sposób sprawdzenia, czy wartość jest pustym ciągiem w instrukcjach sql Postgres?

Wartość może być wyrażeniem długim, dlatego zaleca się, aby była zapisywana tylko raz w szachu.

Obecnie używam:

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

Ale wygląda trochę brzydko.

stringexpressionmoże być char(n)kolumną lub wyrażeniem zawierającym char(n)kolumny ze spacjami na końcu.

Jaki jest najlepszy sposób?

Andrus
źródło
3
Używanie charjest prawie zawsze złym wyborem ze względu na wypełnienie (i wynikające z tego marnotrawstwo miejsca). Ale poza tym: nie sądzę, aby było lepsze rozwiązanie.
a_horse_with_no_name
Dlaczego brzydki? Logiczne i czytelne.
klin
1
@a_horse_with_no_name: Myślę, że tak.
Erwin Brandstetter

Odpowiedzi:

283

Wyrażenie stringexpression = ''daje:

TRUE   .. for ''(lub dla dowolnego łańcucha składającego się tylko ze spacji z typem danych char(n))
NULL   .. for NULL
FALSE .. dla czegokolwiek innego

Aby więc sprawdzić: stringexpressionjest NULL lub pusty” :

(stringexpression = '') IS NOT FALSE

Lub odwrotne podejście (może być łatwiejsze do odczytania):

(stringexpression <> '') IS NOT TRUE

Działa dla każdego typu postaci, w tym char(n). Podręcznik o operatorach porównania.

Lub użyj oryginalnego wyrażenia bez trim(), co jest kosztownym szumem char(n)(patrz poniżej), lub niepoprawne dla innych typów znaków: łańcuchy zawierające tylko spacje byłyby traktowane jako pusty łańcuch.

coalesce(stringexpression, '') = ''

Ale wyrażenia na górze są szybsze.

Stwierdzenie czegoś przeciwnego jest jeszcze prostsze: stringexpressionnie ma wartości NULL ani pustej” :

stringexpression <> ''

O char(n)

Jest to o rodzaju danych char(n), skrót: character(n). ( char/ charactersą skrótem od char(1)/ character(1).) Jego użycie jest odradzane w Postgres :

W większości sytuacji textlub character varyingpowinno być używane zamiast tego.

Nie należy mylić char(n)z rodzaju inne, przydatne, charakter varchar(n), varchar, textlub"char" (z podwójnych cudzysłowów).

W char(n)na pusty ciąg nie różni się od jakiegokolwiek innego napisu, składające się tylko z przestrzeni. Wszystkie te elementy są składane do n spacji char(n)zgodnie z definicją typu. Wynika z tego logicznie, że powyższe wyrażenia działają char(n)również - tak samo jak te (które nie działałyby dla innych typów znaków):

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

Próbny

Pusty ciąg równa się dowolnemu ciągowi spacji, gdy jest rzutowany na char(n):

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

Wynik:

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

Sprawdź „pusty lub pusty ciąg” za pomocą 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);

Wynik:

stringexpression | base_test | test1 | test2 | coalesce1 | coalesce2 | coalesce3
------------------ + ----------- + ------- + ------- + --- -------- + ----------- + -----------
 foo | f | f | f | f | f | fa
                  | t | t | t | t | t | t
                  | t | t | t | t | t | t
 null              | null       | t | t | t | t | t

Sprawdź „pusty lub pusty ciąg” za pomocą 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);

Wynik:

stringexpression | base_test | test1 | test2 | coalesce1 | coalesce2 | coalesce3
------------------ + ----------- + ------- + ------- + --- -------- + ----------- + -----------
 foo | f | f | f | f | f | fa
                  | t | t | t | t | f | fa
                  | f | f | f | f | f | fa
 null              | null       | t | t | t | t | fa

db <> skrzypce tutaj
Stare sqlfiddle

Związane z:

Erwin Brandstetter
źródło
2
@a_horse_with_no_name: OP pyta o plik best way to check if value is null or empty string. trim()Połączenie jest (stosunkowo) kosztowny - i po prostu nie jest to konieczne. Dodałem więcej informacji char(n)i „pusty ciąg”.
Erwin Brandstetter
1
Napisałeś, że każde wyrażenie tekstowe zawierające tylko spacje jest równe ''. Czy mogę zdjąć wykończenie i użyć coalesce(stringexpression,'')=''do sprawdzenia. Wydaje mi się to bardziej czytelne w porównaniu z twoją odpowiedzią.
Andrus
1
@Andrus: Tak, możesz. Dodałem to i trochę więcej do odpowiedzi.
Erwin Brandstetter
3
select coalesce(' ', '') = '' zwraca false. Tak więc TRIM () jest wymagane
Andrus
1
Ale coalesce(' '::char(5), '') = ''tak nie jest. W każdym razie użyłbym jednego z dwóch górnych wyrażeń, które działają dla dowolnego typu znaków, są najszybsze i najczystsze.
Erwin Brandstetter
46

Aby sprawdzić, czy są puste i puste:

coalesce(string, '') = ''

Aby sprawdzić null, puste i spacje (przyciąć ciąg)

coalesce(TRIM(string), '') = ''
sam
źródło
3
Podoba mi się ta prostota / jasność tej odpowiedzi.
stwr667
12

Sprawdzanie długości sznurka również działa i jest zwarte:

where length(stringexpression) > 0;
yglodt
źródło
Czy sprawdziłeś to w przypadku NULL?
Flinsch
1
Tak. Nie zwraca pustych ani pustych pól łańcuchowych.
yglodt
Jeśli chcesz tylko sprawdzić tylko puste wartości, spróbuj tego -> where length(stringexpression) = 0;. To działa dla mnie.
Kushan Gunasekera
2

Jeśli na końcu mogą znajdować się puste spacje, prawdopodobnie nie ma lepszego rozwiązania. COALESCEjest tylko dla problemów takich jak twój.

Świstak35
źródło
1

Coś, czego używają ludzie, to stringexpression > ''. Może nie jest to najszybszy, ale tak się składa, że ​​jest jednym z najkrótszych.

Wypróbowałem to na MS SQL, a także na PostgreSQL.

TarasB
źródło
1

w inny sposób

nullif(trim(stringExpression),'') is not null
Mowazzem Hosen
źródło
1
najlepsza odpowiedź IMHO
Jeff
0

Preferowany przeze mnie sposób porównywania pól dopuszczających wartość null to: NULLIF (nullablefield,: ParameterValue) IS NULL AND NULLIF (: ParameterValue, nullablefield) IS NULL. Jest to kłopotliwe, ale ma uniwersalne zastosowanie, podczas gdy Coalesce w niektórych przypadkach jest niemożliwe.

Drugie i odwrotne użycie wartości NULLIF wynika z tego, że „NULLIF (nullablefield,: ParameterValue) IS NULL” zawsze zwróci wartość „true”, jeśli pierwszy parametr ma wartość null.

Danilo da Silva
źródło
0

Jeśli baza danych ma dużą liczbę rekordów, null checkmoże to zająć więcej czasu, możesz użyć sprawdzania wartości null na różne sposoby, na przykład: 1) where columnname is null 2) where not exists() 3)WHERE (case when columnname is null then true end)

Ambrish Rajput
źródło
0

Wiele odpowiedzi to najkrótsza droga, niekoniecznie najlepsza, jeśli kolumna zawiera wiele wartości zerowych. Przerwanie sprawdzeń pozwala optymalizatorowi na szybszą ocenę testu, ponieważ nie musi on wykonywać pracy nad innym warunkiem.

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

Porównanie ciągów nie musi być oceniane, ponieważ pierwszy warunek jest fałszywy.

John VE
źródło