2010-10-28 3 views
6

tengo un procedimiento almacenado con un parámetro name que quiero utilizar en una cláusula where para que coincida con el valor de una columna es decir, algo así como¿Cómo debo tratar los parámetros nulos en un procedimiento almacenado PL/SQL cuando quiero usarlos en las comparaciones?

where col1 = name 

Ahora por supuesto esto no coincide con null a null debido a la forma null funciona. ¿Necesito hacer

where ((name is null and col1 is null) or col1 = name) 

en situaciones como ésta o hay una manera más concisa de hacerlo?

+0

ver una pregunta duplicado y sus respuestas aquí: http://stackoverflow.com/questions/5014620/oracle-pl-sql-null-input-parameter-where-condition –

+0

@RuslansUralovs Esto no es un duplicado. Esta pregunta se trata de comparar nulos, la otra se trata de excluir el parámetro por completo cuando es nulo. – Shawn

Respuesta

7

puede utilizar decode función de la siguiente manera:

where decode(col1, name, 0) is not null 

Cite de referencia SQL:

En una función DECODE, Oracle considera dos nulos a ser equivalentes.

+0

Eso es algo que nunca supe sobre 'DECODE'. Pero ¿no debería ser 'donde decodificar (col1, name, 0,1) = 0' o algo así? –

+2

@ Adam Hawkes en su ejemplo, ha especificado el argumento 4-ésimo de 'decode' - valor predeterminado si no se han encontrado coincidencias. Si el 4º argumento no se especifica 'decode' devuelve' null', por lo tanto, nuestros ejemplos de código son idénticos si nos referimos a la pregunta del autor: compare los valores 'null'. – andr

5

Lo que ha hecho es correcto. Hay una manera más concisa, pero no es realmente mejor:

where nvl(col1,'xx') = nvl(name,'xx') 

El problema es que usted tiene que asegurarse de que el valor que se utiliza para los nulos ('xx' es mi ejemplo) podría en realidad no ser un valor real en los datos.

6

Creo que su propia sugerencia es la mejor manera de hacerlo.

4

Si col1 está indexado, que sería mejor (en cuanto al rendimiento) para dividir la consulta en dos:

SELECT * 
FROM mytable 
WHERE col1 = name 
UNION ALL 
SELECT * 
FROM mytable 
WHERE name IS NULL AND col1 IS NULL 

De esta manera, Oracle pueden optimizar tanto las consultas de forma independiente, por lo que la primera o la segunda parte ganado' se puede ejecutar realmente dependiendo de name pasado siendo NULL o no.

Oracle, sin embargo, no indiza NULL valores de campos, por lo que buscar un valor NULL siempre dará como resultado una exploración de tabla completa.

Si la tabla es grande, tiene unos NULL valores y que la búsqueda de ellos con frecuencia, puede crear un índice basado en las funciones:

CREATE INDEX ix_mytable_col1__null ON mytable (CASE WHEN col1 IS NULL THEN 1 END) 

y utilizarlo en una consulta:

SELECT * 
FROM mytable 
WHERE col1 = name 
UNION ALL 
SELECT * 
FROM mytable 
WHERE CASE WHEN col1 IS NULL THEN 1 END = CASE WHEN name IS NULL THEN 1 END 
+0

valores nulos indexación solo en índices de mapa de bits ... – walla

+3

El optimizador no sabrá si el parámetro (que se convierte en una variable de vinculación) es nulo o no, por lo que ejecutará ambas consultas, probablemente más lento ya que probablemente implique una tabla completa escanear Y una lectura indexada (o el segundo escaneo completo de la tabla!) –

+2

El optimizador no lo hará, pero el motor de consulta lo hará. La segunda consulta aparecerá en el plan, pero no se ejecutará realmente. Solo inténtalo. – Quassnoi

-1
SELECT * FROM table 
WHERE paramater IS NULL OR column = parameter; 
Cuestiones relacionadas