2009-12-02 19 views
10

Así que le pedí a question esta mañana, que no he corregido correctamente, así que recibí muchas respuestas sobre por qué NULL en comparación con algo dará NULL/FALSE.probando la desigualdad con columnas que pueden ser nulas

Mi pregunta real era, ¿cuál es la moda honrada en el tiempo en que los chicos de DB prueban las desigualdades para dos columnas que pueden ser ambas Nulas. Mi pregunta es exactamente lo contrario de este question.

Los requisitos son los siguientes, A y B son dos columnas:
a) si A y B son ambos NULL, que son iguales, devolver FALSE
b) si A y B son ambos no es NULL, a continuación, volver Un <> B
c) si a o B son NULL, que no son iguales, return TRUE

Respuesta

8

Dependiendo del tipo de datos y los posibles valores para las columnas:

COALESCE(A, -1) <> COALESCE(B, -1) 

el truco es encontrar un valor (aquí he usado -1) th a voluntad NUNCA aparecen en sus datos.

La otra manera sería:

(A <> B) OR (A IS NOT NULL AND B IS NULL) OR (A IS NULL AND B IS NOT NULL) 

Esto puede ser un problema dependiendo de cómo su RDBMS particular, se ocupa de los nulos. Según el estándar ANSI, esto debería darle lo que desea, pero quién sigue los estándares de todos modos. :)

P.S. - También debo señalar que el uso de la función COALESCE puede invalidar el uso de índices al comparar las columnas. Verifique su plan de consulta y el rendimiento de la consulta para ver si eso es un problema.

P.P.S. - Me acabo de dar cuenta de que OMG Ponies mencionó que Informix no es compatible con COALESCE. Es una función estándar de ANSI, creo, pero vea lo que dije antes sobre los estándares ...

+0

@Tom: No es que no lo admita, solo que parece depender de la versión/edición. –

+0

Y envolver la columna en cualquier función significa no usar un índice si está presente. –

+0

La consulta de fusión no funciona si -1 es un valor válido para la columna. Si lo codifico así, y hoy -1 no es un valor válido, y luego se convierte en un valor válido, este será un error donde un campo nulo es igual a un campo -1. – rouble

0

Si desea estar seguro de cómo se manejan los NULL, deberá usar lo que Informix admita para la verificación nula. No he aparecido mucho, salvo que la versión SE no es compatible con COALESCE, pero sí admite DECODE y posiblemente CASE.

WHERE COALESCE(t.a, 0) != COALESCE(t.b, 0) 
WHERE DECODE(NULL, 0, t.a) != DECODE(NULL, 0, t.b) 
+0

Coalescencia a 0 es probablemente malo ya que sería igual a falso. –

+0

@jleedev: El requisito es que 'a' y' b' no se correspondan entre sí. –

+0

Si uno es '0' y el otro es' NULL', entonces obtienes '0! = 0', que es falso donde debería ser verdadero. –

3

Yo personalmente escribo la expresión que se le ocurrió, especialmente si se espera que la tabla crezca. Envolver las columnas en llamadas de función perjudica el rendimiento haciéndolo para que el motor no pueda usar ningún índice que tenga en esas columnas. Por supuesto, en una tabla pequeña, esto puede no ser un problema, pero aún me gusta hacerlo explícitamente en caso de que una mesa termine creciendo.

0

Para SQL Server, utilice:

WHERE ISNULL(A, '') <> ISNULL(B, '') 
+1

Esto no funciona si '' es un valor válido para la columna. – rouble

+1

La base de datos es informix –

1

puede intentar algo como esto en Informix?

CASE 
    WHEN a IS NULL AND B IS NULL THEN false 
    WHEN a IS NULL OR B IS NULL THEN true 
    ELSE a <> B 
END 

de IBM Informix Guide to SQL: Syntax , CASE Expressions

+0

No sé si eso funcionaría en una cláusula WHERE –

+0

Sí, CASE-WHEN, COALESCE y NULLIF son todas ANSI SQL92 y funcionan en WHERE. – bobince

0

El problema es que a<>b (o a=b) da NULL, no 1 o 0 cuando uno o ambos operandos son NULL.Esto no importa para el caso = porque es NULL OR 11 y NULL OR 0 es NULL que se comporta como 0 para la selección en una cláusula WHERE.

Se podría decir:

a<>b OR (a IS NULL)<>(b IS NULL) 

Sin embargo necesidad de hacerlo de cualquier manera puede ser una señal de que estás haciendo mal uso NULL y debe considerar el cambio del esquema que se utiliza algún otro valor NOT NULL para indicar esta condición comparable .

Por ejemplo, si usted tiene una tabla con una columna persontitle, no utilizan NULL para indicar que no tienen ningún título; ese no es un dato "perdido", es solo que no existe un título. Así que guárdelo como una cadena vacía '' que puede comparar felizmente con otras cadenas vacías. (Bueno, a menos que ejecute Oracle, por supuesto, con su problema Empty String ...)

+0

En realidad, mi consulta no funciona. Si solo uno de A o B es NULO, mi consulta arrojará FALSO, lo cual es incorrecto. – rouble

+0

Ah ... en realidad no es 0 (falso), está devolviendo NULL debido a la comparación ... pero luego en el caso de iguales no importa y en los desiguales sí lo hace. Editando ... – bobince

+0

@bobince su solución es muy elegante y correcta, sin embargo, da un error de sintaxis en informix 11.5 – rouble

0

IBM Informix Dynamic Server tiene una visión un tanto peculiar de los booleanos por una variedad de razones históricas (también conocidas como "malas"). Adaptando la idea sugerida por @astander, esta expresión CASE 'funciona', pero yo sería el primero en decir 'no obvio' (mira, ¡lo dije antes que tú!). La fase de configuración:

create table x(a int, b int); 
insert into x values(null, null); 
insert into x values(null, 1); 
insert into x values(1, null); 
insert into x values(1, 1); 
insert into x values(1, 2); 

la instrucción SELECT:

SELECT * 
    FROM x 
    WHERE CASE 
      WHEN a IS NULL AND b IS NULL THEN 'f'::BOOLEAN 
      WHEN a IS NULL OR b IS NULL THEN 't'::BOOLEAN 
      WHEN a != b     THEN 't'::BOOLEAN 
      ELSE        'f'::BOOLEAN 
      END 
; 

El resultado de esta consulta es:

    1 
     1   
     1   2 

Problemas:

  • IDS no reconoce falsa o VERDADERO o DESCONOCIDO como palabras clave.
  • IDS no reconoce expresiones booleanas como 'a! = B' (o 'a <> b') como tales.

Sí, me duele mucho tener que decir esto.

0

Si

where ((A=B) OR (A IS NULL AND B IS NULL)) 

es por la igualdad, entonces ¿por qué no usar:

where NOT (
    ((A=B) OR (A IS NULL AND B IS NULL)) 
) 

para la desigualdad?

Cuestiones relacionadas