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?


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:


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

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;

¿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.


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.



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.


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)


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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.