La mejor manera de verificar el "valor vacío o nulo"

176

¿Cuál es la mejor manera de verificar si el valor es una cadena nula o vacía en las declaraciones SQL de Postgres?

El valor puede ser una expresión larga, por lo que es preferible que se escriba solo una vez bajo control.

Actualmente estoy usando:

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

Pero se ve un poco feo.

stringexpressionpuede ser una char(n)columna o expresión que contenga char(n)columnas con espacios finales.

¿Cuál es la mejor manera?

Andrus
fuente
3
Usar chares casi siempre la elección incorrecta debido al relleno (y al desperdicio de espacio resultante). Pero aparte de eso: no creo que haya una mejor solución.
a_horse_with_no_name
¿Por qué feo? Lógico y legible.
klin
1
@a_horse_with_no_name: creo que sí.
Erwin Brandstetter

Respuestas:

283

La expresion stringexpression = '' produce:

TRUE   .. for ''(o para cualquier cadena que consista solo en espacios con el tipo de datos char(n))
NULL   .. forNULL
FALSE ... para cualquier otra cosa

Para verificar: " stringexpressiones NULL o está vacío" :

(stringexpression = '') IS NOT FALSE

O el enfoque inverso (puede ser más fácil de leer):

(stringexpression <> '') IS NOT TRUE

Funciona para cualquier tipo de personaje incluido char(n). El manual sobre operadores de comparación.

O use su expresión original sin trim(), que es un ruido costoso para char(n)(ver más abajo), o incorrecto para otros tipos de caracteres: las cadenas que consisten en solo espacios pasarían como cadenas vacías.

coalesce(stringexpression, '') = ''

Pero las expresiones en la parte superior son más rápidas.

Afirmar lo contrario es aún más simple: " stringexpressionno es NULL ni está vacío" :

stringexpression <> ''

Acerca de char(n)

Esto es sobre el tipo de datos char(n), la abreviatura de: character(n). ( char/ characterson la abreviatura de char(1)/ character(1).) Se desaconseja su uso en Postgres :

En la mayoría de las situaciones texto character varyingdebería usarse en su lugar.

No se debe confundir char(n)con otro tipo, útil, carácter varchar(n), varchar, texto"char" (con comillas dobles).

En char(n)una cadena vacía no es diferente de cualquier otra cadena que consista solo en espacios. Todos estos se pliegan en n espacios en char(n)cada definición del tipo. Se deduce lógicamente que las expresiones anteriores también funcionan char(n), tanto como estas (que no funcionarían para otros tipos de caracteres):

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

Manifestación

La cadena vacía equivale a cualquier cadena de espacios cuando se lanza a char(n):

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

Resultado:

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

Prueba de "cadena nula o vacía" 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);

Resultado:

stringexpression | prueba_base | prueba1 | test2 | coalesce1 | coalesce2 | coalesce3
------------------ + ----------- + ------- + ------- + --- -------- + ----------- + -----------
 foo | f | f | f | f | f | F
                  El | t | t | t | t | t | t
                  El | t | t | t | t | t | t
 nulo              | nulo       | t | t | t | t | t

Prueba de "cadena nula o vacía" 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);

Resultado:

stringexpression | prueba_base | prueba1 | test2 | coalesce1 | coalesce2 | coalesce3
------------------ + ----------- + ------- + ------- + --- -------- + ----------- + -----------
 foo | f | f | f | f | f | F
                  El | t | t | t | t | f | F
                  El | f | f | f | f | f | F
 nulo              | nulo       | t | t | t | t | F

db <> violín aquí
Viejo sqlfiddle

Relacionado:

Erwin Brandstetter
fuente
2
@a_horse_with_no_name: OP pregunta por el best way to check if value is null or empty string. La trim()llamada es (comparativamente) costosa, y simplemente no es necesaria. Agregué más sobre char(n)y "cadena vacía".
Erwin Brandstetter
1
Usted escribió que cualquier expresión de cadena que contenga solo espacios es igual a ''. ¿Puedo quitar la moldura y usar coalesce(stringexpression,'')=''para verificar? Esto me parece más legible en comparación con tu respuesta.
Andrus
1
@Andrus: Sí, puedes. Agregué eso y algo más a la respuesta.
Erwin Brandstetter
3
select coalesce(' ', '') = '' devuelve falso Por lo tanto, se requiere TRIM ()
Andrus
1
Pero coalesce(' '::char(5), '') = ''no lo hace. En cualquier caso, usaría una de las dos expresiones principales, que funcionan para cualquier tipo de carácter y son más rápidas y limpias.
Erwin Brandstetter
46

Para verificar nulo y vacío:

coalesce(string, '') = ''

Para verificar nulo, vacío y espacios (recortar la cadena)

coalesce(TRIM(string), '') = ''
sam
fuente
3
Me gusta esta simplicidad / claridad de esta respuesta.
stwr667
12

Verificar la longitud de la cadena también funciona y es compacto:

where length(stringexpression) > 0;
yglodt
fuente
¿Comprobó esto para el caso NULL?
Flinsch
1
Sí, lo hice. No devuelve campos de cadena vacíos ni nulos.
yglodt
Si solo necesita verificar los valores vacíos, intente esto -> where length(stringexpression) = 0;. Esto funciona para mi.
Kushan Gunasekera
2

Si puede haber espacios finales vacíos, probablemente no haya una mejor solución. COALESCEes solo para problemas como el tuyo.

Świstak35
fuente
1

Algo que vi a la gente usando es stringexpression > '' . Este puede no ser el más rápido, pero resulta ser uno de los más cortos.

Lo probé en MS SQL y en PostgreSQL.

TarasB
fuente
1

otra forma es

nullif(trim(stringExpression),'') is not null
Mowazzem Hosen
fuente
1
mejor respuesta en mi humilde opinión
Jeff
0

Mi forma preferida de comparar campos anulables es: NULLIF (nullablefield,: ParameterValue) IS NULL AND NULLIF (: ParameterValue, nullablefield) IS NULL. Esto es engorroso pero es de uso universal, mientras que la fusión es imposible en algunos casos.

El segundo uso inverso de NULLIF se debe a que "NULLIF (nullablefield,: ParameterValue) IS NULL" siempre devolverá "verdadero" si el primer parámetro es nulo.

Danilo da Silva
fuente
0

Si la base de datos tiene una gran cantidad de registros, null checkpuede tomar más tiempo, puede usar la verificación nula de diferentes maneras, como: 1) where columnname is null 2) where not exists() 3)WHERE (case when columnname is null then true end)

Rajput ambrish
fuente
0

Muchas de las respuestas son el camino más corto, no necesariamente el mejor si la columna tiene muchos valores nulos. Romper los controles le permite al optimizador evaluar el control más rápido ya que no tiene que trabajar en la otra condición.

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

La comparación de cadenas no necesita ser evaluada ya que la primera condición es falsa.

John VE
fuente