Der beste Weg, um nach einem leeren oder Nullwert zu suchen

176

Wie kann am besten überprüft werden, ob der Wert in Postgres-SQL-Anweisungen null oder eine leere Zeichenfolge ist?

Der Wert kann ein langer Ausdruck sein, daher ist es vorzuziehen, dass er nur einmal in der Prüfung geschrieben wird.

Derzeit verwende ich:

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

Aber es sieht ein bisschen hässlich aus.

stringexpressionkann eine char(n)Spalte oder ein Ausdruck sein, der char(n)Spalten mit nachgestellten Leerzeichen enthält.

Was ist der beste Weg?

Andrus
quelle
3
Die Verwendung charist aufgrund der Polsterung (und der daraus resultierenden Platzverschwendung) fast immer die falsche Wahl. Aber abgesehen davon: Ich glaube nicht, dass es eine bessere Lösung gibt.
a_horse_with_no_name
Warum hässlich? Logisch und lesbar.
klin
1
@a_horse_with_no_name: Ich denke es gibt.
Erwin Brandstetter

Antworten:

282

Der Ausdruck stringexpression = '' ergibt:

TRUE   .. für ''(oder für jede Zeichenfolge, die nur aus Leerzeichen mit dem Datentyp besteht char(n))
NULL   .. fürNULL
FALSE .. für alles andere

So überprüfen Sie: " stringexpressionist entweder NULL oder leer" :

(stringexpression = '') IS NOT FALSE

Oder der umgekehrte Ansatz (möglicherweise leichter zu lesen):

(stringexpression <> '') IS NOT TRUE

Funktioniert für jeden Zeichentyp einschließlich char(n). Das Handbuch zu Vergleichsoperatoren.

Oder verwenden Sie Ihren ursprünglichen Ausdruck ohne trim(), was für char(n)(siehe unten) kostspielig oder für andere Zeichentypen falsch ist: Zeichenfolgen, die nur aus Leerzeichen bestehen, werden als leere Zeichenfolge übergeben.

coalesce(stringexpression, '') = ''

Die Ausdrücke oben sind jedoch schneller.

Das Gegenteil zu behaupten ist noch einfacher: " stringexpressionist weder NULL noch leer" :

stringexpression <> ''

Über char(n)

Hier geht es um den Datentyp char(n), kurz für : character(n). ( char/ characterstehen für char(1)/ character(1).) Von seiner Verwendung wird in Postgres abgeraten :

In den meisten Situationen textoder character varyingsollte stattdessen verwendet werden.

Nicht zu verwechseln char(n)mit anderen, nützlich, Charaktertypen varchar(n), varchar, textoder"char" (mit Anführungszeichen).

In char(n)einer leeren Zeichenfolge ist nicht anders als jede andere Zeichenfolge , die nur aus Leerzeichen. Alle diese sind gemäß Definition des Typs auf n Leerzeichen gefaltet char(n). Daraus folgt logischerweise, dass die obigen Ausdrücke auch funktionieren char(n)- genauso wie diese (was für andere Zeichentypen nicht funktionieren würde):

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

Demo

Eine leere Zeichenfolge entspricht einer beliebigen Zeichenfolge von Leerzeichen, wenn sie in Folgendes umgewandelt wird char(n):

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

Ergebnis:

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

Test auf "null oder leere Zeichenfolge" mit 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);

Ergebnis:

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

Test auf "null oder leere Zeichenfolge" mit 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);

Ergebnis:

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

db <> hier fummeln
Alte sqlfiddle

Verbunden:

Erwin Brandstetter
quelle
2
@a_horse_with_no_name: OP fragt nach dem best way to check if value is null or empty string. Der trim()Anruf ist (vergleichsweise) teuer - und einfach nicht notwendig. Ich habe mehr über char(n)und "leere Zeichenfolge" hinzugefügt .
Erwin Brandstetter
1
Sie haben geschrieben, dass jeder Zeichenfolgenausdruck, der nur Leerzeichen enthält, gleich ist ''. Kann ich die Verkleidung entfernen und coalesce(stringexpression,'')=''zur Überprüfung verwenden ? Dies erscheint mir im Vergleich zu Ihrer Antwort besser lesbar.
Andrus
1
@Andrus: Ja, das kannst du. Ich habe das und noch etwas mehr zur Antwort hinzugefügt.
Erwin Brandstetter
3
select coalesce(' ', '') = '' gibt false zurück. Also ist TRIM () erforderlich
Andrus
1
Aber coalesce(' '::char(5), '') = ''nicht. Ich würde auf jeden Fall einen der beiden obersten Ausdrücke verwenden, die für jeden Zeichentyp funktionieren und am schnellsten und saubersten sind.
Erwin Brandstetter
46

So prüfen Sie, ob null und leer sind:

coalesce(string, '') = ''

Um nach Nullen, Leerzeichen und Leerzeichen zu suchen (schneiden Sie die Zeichenfolge ab)

coalesce(TRIM(string), '') = ''
Sam
quelle
3
Ich mag diese Einfachheit / Klarheit dieser Antwort.
stwr667
11

Das Überprüfen der Länge der Zeichenfolge funktioniert ebenfalls und ist kompakt:

where length(stringexpression) > 0;
yglodt
quelle
Haben Sie dies für den Fall NULL überprüft?
Flinsch
1
Ja, habe ich. Es werden weder leere noch Nullzeichenfolgenfelder zurückgegeben.
Yglodt
Wenn Sie nur leere Werte überprüfen müssen, versuchen Sie dies -> where length(stringexpression) = 0;. Das funktioniert bei mir.
Kushan Gunasekera
2

Wenn möglicherweise leere Leerzeichen vorhanden sind, gibt es wahrscheinlich keine bessere Lösung. COALESCEist nur für Probleme wie deine.

Świstak35
quelle
1

Etwas, das ich gesehen habe, ist stringexpression > ''. Dies ist vielleicht nicht die schnellste, aber zufällig eine der kürzesten.

Versuchte es sowohl auf MS SQL als auch auf PostgreSQL.

TarasB
quelle
1

Ein anderer Weg ist

nullif(trim(stringExpression),'') is not null
Mowazzem Hosen
quelle
1
beste Antwort IMHO
Jeff
0

Meine bevorzugte Methode zum Vergleichen von nullbaren Feldern ist: NULLIF (nullablefield ,: ParameterValue) IST NULL UND NULLIF (: ParameterValue, nullablefield) IST NULL. Dies ist umständlich, aber von universellem Nutzen, während Coalesce in einigen Fällen unmöglich ist.

Die zweite und umgekehrte Verwendung von NULLIF ist, weil "NULLIF (nullablefield ,: ParameterValue) IS NULL" immer "true" zurückgibt, wenn der erste Parameter null ist.

Danilo da Silva
quelle
0

Wenn eine Datenbank mit einer großen Anzahl von Datensätzen null checklänger dauern kann, können Sie die Nullprüfung auf verschiedene Arten verwenden, z. B.: 1) where columnname is null 2) where not exists() 3)WHERE (case when columnname is null then true end)

Ambrish Rajput
quelle
0

Viele der Antworten sind der kürzeste Weg, nicht unbedingt der beste, wenn die Spalte viele Nullen enthält. Durch das Aufbrechen der Überprüfungen kann der Optimierer die Überprüfung schneller auswerten, da er nicht an der anderen Bedingung arbeiten muss.

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

Der Zeichenfolgenvergleich muss nicht ausgewertet werden, da die erste Bedingung falsch ist.

John VE
quelle