2011-02-16 18 views
5

A partir de ahora estoy usando IF ELSE para manejar esta condiciónOracle PL SQL nulo de parámetro de entrada donde la condición

IF INPUT_PARAM IS NOT NULL 

    SELECT ... FROM SOMETABLE WHERE COLUMN = INPUT_PARAM 
ELSE 
    SELECT ... FROM SOMETABLE 

¿Hay alguna forma mejor de hacer esto en una sola consulta sin bucles IF ELSE. A medida que la consulta se vuelve compleja, habrá más parámetros de entrada como este y la cantidad de IF ELSE requerida sería demasiado.

+0

Ver una pregunta duplicada y respuestas aquí: http://stackoverflow.com/questions/4042496/how-should-i-deal-with-null-parameters-in-a-pl-sql-stored-procedure-when-i-want –

Respuesta

9

Un método sería el uso de una variante de

WHERE column = nvl(var, column) 

Hay dos trampas aquí, sin embargo:

  1. si la columna es anulable, esta cláusula filtrará valores nulos mientras que en su pregunta no filtraría los valores nulos en el segundo caso. Usted puede modificar esta cláusula para tomar en cuenta los valores nulos pero resulta feo:

    WHERE nvl(column, impossible_value) = nvl(var, impossible_value) 
    

    Por supuesto, si de alguna manera el impossible_value se inserta cada vez que se ejecutará en algún otro tipo de problemas (FUN).

  2. El optimizador no entiende correctamente este tipo de cláusula. A veces se generará un plan con UNION ALL, pero si hay más de un par de nvl, obtendrá un escaneo completo incluso si hay índices perfectamente válidos.

Por eso, cuando hay un montón de parámetros (varios campos de búsqueda en una gran forma, por ejemplo), me gusta utilizar SQL dinámico:

DECLARE 
    l_query VARCHAR2(32767) := 'SELECT ... JOIN ... WHERE 1 = 1'; 
BEGIN 
    IF param1 IS NOT NULL THEN 
     l_query := l_query || ' AND column1 = :p1'; 
    ELSE 
     l_query := l_query || ' AND :p1 IS NULL'; 
    END IF; 
    /* repeat for each parameter */ 
    ... 
    /* open the cursor dynamically */ 
    OPEN your_ref_cursor FOR l_query USING param1 /*,param2...*/; 
END; 

También puede utilizar EXECUTE IMMEDIATE l_query INTO l_result USING param1;

+0

Gracias por compartir dicha información útil. Me alegro de que las columnas sean "NO NULAS" en esta situación. :) –

3

Esto debería funcionar

SELECT ... FROM SOMETABLE WHERE COLUMN = NVL(INPUT_PARAM, COLUMN) 
Cuestiones relacionadas