Está en la página 1de 3

Ejecución de cursores PLSQL y sentencias DML utilizando SQL dinámico nativo (NativeDynamic SQL

)
la posibilidad de definir un procedimiento PL/SQL en el que se declaren múltiples cursores en base al valor de los parámetros de entrada de dicho procedimiento. Las preguntas suelen incluir condiciones muy variadas, pero lo normal es que los implicados sólo necesiten hacer variable la cláusula WHERE y que el resto del cuerpo del cursor PLSQL se mantenga fijo. Cuando esto ocurre yo siempre contesto remitiendo a los que preguntan al artículo que escribí sobre el paquete estándar PL/SQL DBMS_SQL, un paquete que permite crear sentencias SQL dinámicas. Si he decidido escribir un artículo nuevo al respecto es por el hecho de que resulta mucho más legible un código que utilice directamente SQL dinámico nativo, es decir, un código en el que no se utiliza el paquete estándar DBMS_SQL. A continuación os dejo un sencillo ejemplo de cómo se podría construir, utilizando SQL dinámico nativo, un procedimiento PLSQL en el que se define un cursor cuya cláusula WHERE varíe en función de un parámetro.
CREATE OR REPLACE PROCEDURE varcursor (par1 IN NUMBER DEFAULT NULL) AS l_query VARCHAR2(500); TYPE tcursor IS REF CURSOR; l_cursortcursor; l_cursor_recdba_users%ROWTYPE; BEGIN l_query := 'SELECT * FROM dba_users WHERE 1=1'; IF par1 IS NOT NULL THEN l_query := l_query || ' AND user_id = ' || par1; END IF; OPEN l_cursor FOR l_query; LOOP FETCH l_cursor INTO l_cursor_rec; EXIT WHEN l_cursor%NOTFOUND; DBMS_OUTPUT.PUT_LINE (l_cursor_rec.username); END LOOP; CLOSE l_cursor; END;

En nuestro ejemplo, el procedimiento varcursor sacará por pantalla el username con el user_id que se le pase como parámetro, y si el parámetro se pasa con valor NULL, entonces sacara por pantalla todos los username de la tabla dba_users. Por otro lado, muchas otras preguntas hacen referencia a la utilización de SQL dinámico nativo con sentencias SQL DML. De todas las sentencias DML la que se lleva la palma es las sentencia UPDATE y, en este caso concreto, las preguntas hacen referencia tanto a la posibilidad de utilizar una cláusula WHERE variable, como a la posibilidad de modificar o no una determinada columna en base a si se pasa o no un determinado parámetro.

En conclusión. CREATE OR REPLACE PROCEDURE varupdate (vsal IN NUMBER DEFAULT NULL. sin embargo. BEGIN l_query := 'UPDATE empleados SET fecha_actualizacion = SYSDATE. hemos empleado un IF para así utilizar o no la condición asociada con dicho parámetro. os diré que la implementación de una cláusula WHERE variable se realiza de forma similar a la utilizada en el procedimiento varcursor. dicha columna la hemos incluido en el bloque estático de la sentencia SQL UPDATE utilizando la función NVL(). No obstante. entonces el valor de la columna fecha_actualizacion se actualizará para todos los empleados. entonces actualizaremos la columna salario con el mismo valor que tenía anteriormente. pero si vsal es NULL. veid IN NUMBER DEFAULT NULL) AS l_query VARCHAR2(500). EXECUTE IMMEDIATE l_query USING vsal. sin embargo. Esto es mucho más sencillo que utilizar un IF y cambiar dinámicamente la sentencia UPDATE en base a si el parámetro vsal toma el valor NULL o no. En cambio. puesto que los índices no tienen que reconstruirse cuando el valor de una columna no cambia realmente. hemos utilizado la misma técnica que en el procedimiento varcursor. En el ejemplo podéis ver que el primer parámetro es el que determina si la columna salario se actualiza o no. alguien podría pensar que utilizar el IF puede ahorrar tiempo de procesamiento ya que se evitaría el tener que actualizar una columna innecesariamente. es mejor no utilizar SQL dinámico. el aumento en tiempo de procesamiento es mínimo y lo más conveniente es utilizar SQL estático y la función NVL(). IF par2 IS NOT NULL THEN l_query := l_query || ' AND empleado_id = :veid'. sin embargo.Antes de poneros un ejemplo concreto. entonces el valor de la columna salario continuará siendo el mismo y sólo se habrá actualizado el valor de la columna fecha_actualizacion. salario = NVL(:vsal. salario) WHERE 1=1'. es decir. veid. END IF. para el parámetro que se utiliza en la cláusula WHERE de nuestro UPDATE. ocurriendo lo mismo para la columna salario que . END. de manera que si el parámetro vsal toma el valor NULL. nuestro procedimiento actualizará la columna salario del empleado con id veid al valor vsal. para el caso de que una columna se actualice según se pase o no un determinado parámetro. Y si veid toma el valor de NULL. Veamosahoraunejemploconcreto.

siempre que vsal no sea NULL. . en cuyo caso dicha columna no cambiaría.tomará el valor vsal.