Il modo migliore per verificare "valore vuoto o nullo"


176

Qual è il modo migliore per verificare se il valore è una stringa nulla o vuota nelle istruzioni sql di Postgres?

Il valore può essere espressione lunga, quindi è preferibile che sia scritto solo una volta sotto controllo.

Attualmente sto usando:

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

Ma sembra un po 'brutto.

stringexpressionpuò essere una char(n)colonna o un'espressione contenente char(n)colonne con spazi finali.

Qual è il modo migliore?


3
L'uso charè quasi sempre la scelta sbagliata a causa dell'imbottitura (e della conseguente perdita di spazio). Ma a parte questo: non penso che ci sia una soluzione migliore.
a_horse_with_no_name

Perché brutto? Logico e leggibile.
klin,

1
@a_horse_with_no_name: penso che ci sia.
Erwin Brandstetter,

Risposte:


285

L'espressione stringexpression = ''produce:

TRUE   .. per '' (o per qualsiasi stringa costituita da soli spazi con il tipo di dati char(n))
NULL   .. per NULL
FALSE .. per qualsiasi altra cosa

Quindi per verificare: " stringexpressionè NULL o vuoto" :

(stringexpression = '') IS NOT FALSE

Oppure l'approccio inverso (potrebbe essere più facile da leggere):

(stringexpression <> '') IS NOT TRUE

Lavora per qualsiasi tipo di carattere incluso char(n). Il manuale sugli operatori di confronto.

O usa la tua espressione originale senza trim(), che è costoso rumore per char(n)(vedi sotto), o errata per altri tipi di caratteri: le stringhe costituite solo da spazi passerebbero come stringa vuota.

coalesce(stringexpression, '') = ''

Ma le espressioni in alto sono più veloci.

Affermare il contrario è ancora più semplice: "stringexpression non è né NULL né vuoto" :

stringexpression <> ''

Di char(n)

Questo è circa il tipo di dati char(n), abbreviazione di: character(n). ( char/ charactersono l'abbreviazione di char(1)/ character(1).) Il suo utilizzo è sconsigliato in Postgres :

Nella maggior parte delle situazioni text o character varyingdovrebbe essere usato invece.

Non confondere char(n)con altri utili, tipo, carattere varchar(n), varchar,text o"char" (con virgolette).

In char(n)una stringa vuota non è diverso da qualsiasi altra stringa costituita da soli spazi. Tutti questi sono piegati in n spazi char(n)per definizione del tipo. Segue logicamente che le espressioni precedenti funzionano perchar(n) - proprio come queste (che non funzionerebbero con altri tipi di caratteri):

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

dimostrazione

La stringa vuota è uguale a qualsiasi stringa di spazi quando viene lanciata su char(n):

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

Risultato:

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

Test per "stringa nulla o vuota" con 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);

Risultato:

stringexpression | base_test | test1 | test2 | coalesce1 | coalesce2 | coalesce3
------------------ + ----------- + ------- + ------- + --- -------- + ----------- + -----------
 pippo | 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 per "stringa nulla o vuota" con 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);

Risultato:

stringexpression | base_test | test1 | test2 | coalesce1 | coalesce2 | coalesce3
------------------ + ----------- + ------- + ------- + --- -------- + ----------- + -----------
 pippo | 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 <> violino qui
Vecchio sqlfiddle

Relazionato:


2
@a_horse_with_no_name: OP richiede il best way to check if value is null or empty string. La trim()chiamata è (comparativamente) costosa - e semplicemente non necessaria. Ho aggiunto altro su char(n)"stringa vuota".
Erwin Brandstetter,

1
Hai scritto che qualsiasi espressione di stringa contenente solo spazi è uguale a ''. Posso rimuovere il rivestimento e usarlo coalesce(stringexpression,'')=''per controllare. Questo mi sembra più leggibile rispetto alla tua risposta.
Andrus,

1
@Andrus: Sì, puoi. Ho aggiunto questo e alcuni altri alla risposta.
Erwin Brandstetter,

3
select coalesce(' ', '') = '' restituisce false. Quindi è richiesto TRIM ()
Andrus,

1
Ma coalesce(' '::char(5), '') = ''no. Vorrei usare una delle prime due espressioni in ogni caso, che funzionano per qualsiasi tipo di carattere e sono più veloci e più pulite.
Erwin Brandstetter,

46

Per verificare la presenza di null e vuoto:

coalesce(string, '') = ''

Per verificare la presenza di null, vuoti e spazi (tagliare la stringa)

coalesce(TRIM(string), '') = ''

3
Mi piace questa semplicità / chiarezza di questa risposta.
stwr667,

12

Anche il controllo della lunghezza della stringa funziona ed è compatto:

where length(stringexpression) > 0;

Hai controllato questo per il caso NULL?
Flinsch,

1
Si l'ho fatto. Non restituisce campi stringa vuoti né null.
yglodt

Se hai solo bisogno di controllare solo valori vuoti, prova questo -> where length(stringexpression) = 0;. Questo funziona per me.
Kushan Gunasekera,

2

Se potrebbero esserci spazi finali vuoti, probabilmente non esiste una soluzione migliore. COALESCEè solo per problemi come il tuo.


1

Qualcosa che ho visto usare la gente è stringexpression > ''. Questo potrebbe non essere il più veloce, ma sembra essere uno dei più brevi.

L'ho provato su MS SQL e su PostgreSQL.



0

Il mio modo preferito per confrontare i campi nullable è: NULLIF (nullablefield,: ParameterValue) IS NULL E NULLIF (: ParameterValue, nullablefield) IS NULL. Questo è ingombrante ma è di uso universale mentre in alcuni casi la coalescenza è impossibile.

Il secondo e inverso utilizzo di NULLIF è perché "NULLIF (nullablefield,: ParameterValue) IS NULL" restituirà sempre "true" se il primo parametro è null.


0

Se il database con un numero elevato di record null checkpuò richiedere più tempo, è possibile utilizzare il controllo null in diversi modi come: 1) where columnname is null 2) where not exists() 3)WHERE (case when columnname is null then true end)


0

Molte risposte sono il modo più breve, non necessariamente il modo migliore se la colonna ha molti null. La suddivisione dei controlli consente all'ottimizzatore di valutare il controllo più rapidamente in quanto non deve lavorare sull'altra condizione.

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

Non è necessario valutare il confronto delle stringhe poiché la prima condizione è falsa.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.