0% encontró este documento útil (0 votos)
107 vistas

Oracle

PL/SQL es un lenguaje de programación incorporado en Oracle que permite realizar consultas y manipulación de datos de forma similar a SQL. Los programas PL/SQL se almacenan en la base de datos y se ejecutan en el servidor para ahorrar recursos. Los bloques PL/SQL son la unidad básica de programación y pueden ser anónimos o subprogramas como procedimientos y funciones.

Cargado por

Kasumi Zcream
Derechos de autor
© Attribution Non-Commercial (BY-NC)
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
107 vistas

Oracle

PL/SQL es un lenguaje de programación incorporado en Oracle que permite realizar consultas y manipulación de datos de forma similar a SQL. Los programas PL/SQL se almacenan en la base de datos y se ejecutan en el servidor para ahorrar recursos. Los bloques PL/SQL son la unidad básica de programación y pueden ser anónimos o subprogramas como procedimientos y funciones.

Cargado por

Kasumi Zcream
Derechos de autor
© Attribution Non-Commercial (BY-NC)
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 22

PL/SQL

PL/SQL (Procedural Language/Structured programacin incrustado en Oracle. Query Language) es un lenguaje de

PL/SQL soportar todas las consultas, ya que la manipulacin de datos que se usa es la misma que en SQL, incluyendo nuevas caractersticas: El lenguaje PL/SQL est incorporado en: En un entorno de base de datos los programadores pueden construir bloques PL/SQL para utilizarlos como procedimientos o funciones, o bien pueden escribir estos bloques como parte de scripts SQL*Plus. Los programas o paquetes de PL/SQL se pueden almacenar en la base de datos como otro objeto, y todos los usuarios que estn autorizados tienen acceso a estos paquetes. Los programas se ejecutan en el servidor para ahorrar recursos a los clientes.

Bloque PL/SQL
Bloque es la unidad de estructura bsica en los programas PL/SQL. Supone una mejora en el rendimiento, pues se envan los bloques completos al servidor para ser procesados en lugar de enviar cada secuencia SQL. Partes de un bloque: Zona de declaraciones: zona opcional. Se declaran los objetos locales (variables, constantes...). Zona de instrucciones: zona obligatoria. Zona de tratamiento de excepciones: zona opcional. Se tratan excepciones en el programa.

Forma de crear un bloque: [ DECLARE BEGIN <instrucciones> [ EXCEPTION ] <tratamiento de excepciones> END; / La barra "/" siempre se pone al final para ejecutar el bloque. | IS / AS ]

<declaraciones>

Tipos de bloques

Annimo (sin nombre) Siempre comienza con DECLARE o directamente con BEGIN. Ejemplo 1; BEGIN DBMS_OUTPUT.PUT_LINE (Hola); END; / DBMS_OUTPUT es un depurador de Oracle que sirve para visualizar cualquier cosa, pero antes lo debemos tener activado (en SQL*plus, se activa con el comando SET SERVEROUTPUT ON): SET DECLARE fecha date; BEGIN select sysdate into fecha from dual; dbms_output.put_line (to_char(fecha, 'day", "dd" de "month" de "yyyy", a las "hh24:mi:ss')); END; /

Subprogramas (tienen nombre) Se pueden almacenar en la base de datos. Existen dos tipos de subprogramas: Procedimientos (PROCEDURE) y Funciones (FUNCTION)

Procedimientos en PLSQL

Los procedimientos tienen la utilidad de fomentar la reutilizacin de programas que se usan comnmente. Una vez compilado, queda almacenado en la base de datos (por eso es tambin llamado 'Procedimiento almacenado') y puede ser utilizado por mltiples aplicaciones. La sintaxis es la siguiente CREATE [OR REPLACE] PROCEDURE nombre_procedimiento [nombre_parametro modo tipodatos_parametro ] IS | AS bloque de cdigo

Donde "modo" puede contener los valores IN, OUT, IN OUT. Por defecto tiene el valor IN si no se pone nada. IN indica que el parmetro es de entrada y no se podr modificar. OUT indica que el parmetro es de salida con lo que el procedimiento devolver un valor en l. IN OUT indica que el parmetro es de entrada/salida. Con lo que al llamar al procedimiento se le dar un valor que luego podr ser modificado por el procedimiento y devolver este nuevo valor. "tipodatos_parametro indica el tipo de datos que tendr el parmetro segn lo indicado en Tipos de datos Oracle/PLSQL Para borrar un procedimiento almacenado de la base de datos DROP PROCEDURE nombre_procedimiento Para utilizar un procedimiento almacenado de la base de datos Simplemente se lo llama desde un bloque annimo (desde la lnea de comandos), previamente habiendo inicializado el/los parametro/s (en caso que existan). DECLARE nombre_parametro tipodatos_parametro; BEGIN nombre_parametro tipodatos_parametro := valor_de_inicializacion; nombre_procedimiento (nombre_parametro => nombre_parametro); END; /

El uso de OR REPLACE permite sobrescribir un procedimiento existente. Si se omite, y el procedimiento existe, se producir, un error. Debemos especificar el tipo de datos de cada parmetro. Al especificar el tipo de dato del parmetro no debemos especificar la longitud del tipo, aunque si puede ser utilizando el operador %TYPE. CREATE OR REPLACE PROCEDURE Actualiza_Saldo(cuenta NUMBER, new_saldo NUMBER) IS -- Declaracion de variables locales BEGIN UPDATE SALDOS_CUENTAS SET SALDO = new_saldo, FX_ACTUALIZACION = SYSDATE WHERE CO_CUENTA = cuenta;

END Actualiza_Saldo; Tambin podemos asignar un valor por defecto a los parmetros, utilizando la clusula DEFAULT o el operador de asignacin (:=) . CREATE OR REPLACE PROCEDURE Actualiza_Saldo(cuenta NUMBER, new_saldo NUMBER DEFAULT 10) Una vez creado y compilado el procedimiento almacenado podemos ejecutarlo. Existen dos formas de pasar argumentos a un procedimiento almacenado a la hora de ejecutarlo. Estas son: Notacin posicional: Se pasan los valores de los parmetros en el mismo orden en que el procedure los define. BEGIN Actualiza_Saldo(200501,2500); COMMIT; END; Notacin nominal: Se pasan los valores en cualquier orden nombrando explcitamente el parmetro y su valor separados por el smbolo =>. BEGIN Actualiza_Saldo(cuenta => 200501,new_saldo => 2500); COMMIT; END; Parmetros de Procedimiento Cuando creamos el procedimiento, el parmetro formal define el valor utilizado en la seccin ejecutable del bloque PL/SQL, donde se referencia el parmetro actual cuando se llama al procedimiento. Modos para Parmetros Formales IN Por Defecto. Valor que se pasa al Subprograma. Parmetro formal constante. Parmetro Actual puede ser un literal, expresin, constante o variable inicializada. OUT Tiene que especificarlo. IN OUT Tiene que especificarlo.

Devuelve al entorno de Valor que se pasa al llamada. Subprograma; Devuelve al ent. de llamada Variable no Inicializada. Variable Inicializada.

Tiene que ser una variable.

Tiene que ser una variable.

Ejemplo El ejemplo nos muestra un procedimiento con un parmetro IN. Al ejecutar esta sentencia en SQL*Plus, se crea el procedimiento RAISE_SALARY. Cuando se le llama, RAISE_SALARY toma el parmetro del nmero de empleado y actualiza el registro del empleado con un incremento en su salario del 10%. Para llamar a un procedimiento en SQL*Plus, utilizamos el comando EXECUTE. SQL> execute raise_salary (7369) Para llamar a un procedimiento desde el entorno Procedure Builder, utilizamos una llamada directa. En el prompt Procedure Builder Interpreter, introducimos el nombre del procedimiento y los parmetros actuales. PL/SQL> raise_salary (7369); Los parmetros IN se pasan como constantes desde el entorno de llamada, al procedimiento. Si intentamos cambiar el valor de un parmetro IN, se producir un error. SQL> CREATE OR REPLACE PROCEDURE raise_salary (v_id in emp.empno%TYPE) IS BEGIN UPDATE emp SET sal = sal * 1.10 WHERE empno = v_id; END raise_salary; / Procedure created. SQL> EXECUTE raise_salary (7369) PL/SQL procedure successfully completed. Parmetros OUT: Ejemplo Ejecutar la sentencia de arriba para crear el procedimiento QUERY_EMP. Este procedimiento tiene cuatro parmetros formales; tres de ellos son parmetros OUT que devuelven un valor al entorno de llamada.
SQL> CREATE OR REPLACE PROCEDURE query_emp (v_id IN emp.empno%TYPE, v_name OUT emp.ename%TYPE,

v_salary OUT emp.sal%TYPE, v_comm OUT emp.comm%TYPE) IS BEGIN SELECT ename, sal, comm INTO v_name, v_salary, v_comm FROM emp WHERE empno = v_id; END query_emp; /

Funciones en PLSQL

Una funcin es un bloque de cdigo PL/SQL que tiene las mismas caractersticas que un procedimiento almacenado. La diferencia estriba que una funcin devuelve un valor al retornar. Al devolver un valor puede ser llamada como parte de una expresin. La sintaxis sera CREATE [OR REPLACE] FUNCTION nombre_funcin [nombre_parmetro modo tipodatos_parametro ] RETURN tipodatos_retorno IS | AS bloque de cdigo Donde "modo" puede contener los valores IN, OUT, IN OUT. Por defecto tiene el valor IN si no se pone nada. IN indica que el parmetro es de entrada y no se podr modificar. OUT indica que el parmetro es de salida con lo que la funcion devolver un valor en l. IN OUT indica que el parmetro es de entrada/salida. Con lo que al llamar a la funcion se le dar un valor que luego podr ser modificado por la misma y devolver este nuevo valor. Sin embargo, en este caso solo tendra sentido (por el concepto de funcin en s mismo) declarar parmetros del tipo IN y devolver el valor como retorno de la funcin. "tipodatos_parametro" y "tipodatos_retorno" indican el tipo de datos que tendr el parmetro y el valor de retorno de la funcin respectivamente segn lo indicado en Tipos de datos Oracle/PLSQL Para borrar una funcin de la base de datos DROP FUNCTION nombre_funcin

Ejemplo de creacin de una funcin CREATE OR REPLACE FUNCTION obtener_salario (w_cdigo_emp IN emp.cdigo_emp%TYPE) RETURN NUMBER IS w_salario emp.salario_emp%TYPE;

BEGIN SELECT salario_emp INTO w_salario FROM emp WHERE cdigo _emp = w_cdigo_emp; RETURN w_salario; END obtener_salario; Cada funcin debe devolver un valor del tipo especificado utilizando la sentencia RETURN. Ejecucin de Funciones Llame a la funcin como parte de una expresin PL/SQL. Cree una variable host que recoja el valor devuelto. Ejecute la funcin. La variable host se volcar en valor de RETURN.

Ejemplo Ejecutar la funcin GET_SAL desde SQL*Plus: 1. Ejecutar la sentencia para crear la funcin almacenada GET_SAL. 2. Crear una variable host la cual ser popularizada por la sintaxis RETURN (variable), dentro de la funcin. SQL> START get_salary.sql 3. Llamar a GET_SAL creando una expresin PL/SQL, utilizando la sintaxis EXECUTE. Dar un valor para el parmetro (en este ejemplo es el nmero de identificacin del empleado). El valor que devuelve la funcin lo mantendr la variable host, g_salary. Observamos que se utilizan los dos puntos (:) para referenciar a la variable host. SQL> VARIABLE g_salary number 4. Ver los resultados utilizando la sintaxis PRINT. El empleado Miller, empno 7934, gana al mes 1300. SQL> PRINT g_salary G_SALARY -----------------1300 Desde dnde llamar a una Funcin de Usuario Las funciones PL/SQL definidas por el usuario, pueden llamarse desde cualquier expresin SQL cuando pueda llamarse a una funcin built-in. Como columna de un SELECT

Condiciones en clasulas WHERE y HAVING Clasulas CONNECT BY, START WITH, ORDER BY, y GROUP BY Clasula VALUES de un comando INSERT Clasula SET de un comando UPDATE Llamada a Funciones desde Expresiones SQL: Restricciones Una funcin PL/SQL definida por el usuario debe cumplir ciertos requisitos para que pueda ser llamada desde expresiones SQL. Una funcin de usuario tiene que ser una funcin almacenada. Tiene que ser una funcin de registro, no de grupo. Slo se sirve de comandos IN. Los tipos de datos tienen que ser CHAR, DATE, o NUMBER, no tipos PL/SQL types como BOOLEAN, RECORD, o TABLE. El tipo de Return tiene que ser un tipo interno del serividor Oracle. No se permiten comandos INSERT, UPDATE, o DELETE. Las llamadas a subprogramas que rompan estas restricciones, tampoco se permiten. Los procedimientos y funciones se pueden agrupar en unas estructuras llamadas Paquetes.

Paquetes

Se usan para agrupar procedimientos y funciones. Facilitan la descomposicin modular y el mantenimiento. Partes de un paquete:

Especificacin: Se declaran los elementos pblicos que componen el paquete, es decir, variables, funciones y procedimientos que sern accesibles desde fuera del paquete. De las funciones y procedimientos slo indicamos la cabecera, no el cuerpo.

CREATE [OR REPLACE] PACKAGE nombrePaquete IS|AS variables, constantes, cursores, etc (pblicos) cabecera de procedimientos y funciones END nombrePaquete;

Cuerpo:

Se realiza la definicin de los procedimientos indicados en la especificacin del paquete. Tambin es posible la declaracin de miembros privados. Una vez terminado el paquete se compila.

CREATE [OR REPLACE] PACKAGE BODY nombrePaquete IS|AS variables, constantes, cursores, etc (privados) cuerpo de procedimientos y funciones END nombrePaquete; Ventajas del uso de Paquetes Dentro de las ventajas que ofrece el uso de paquetes podemos citar que: Permite modularizar el diseo de nuestra aplicacin El uso de Paquetes permite encapsular elementos relacionados entre s (tipos, variables, procedimientos, funciones) en un nico mdulo PL/Sql que llevar un nombre que identifique la funcionalidad del conjunto. Otorga flexibilidad al momento de disear la aplicacin En el momento de disear una aplicacin todo lo que necesitaremos inicialmente es la informacin de interfaz en la especificacin del paquete. Puede codificarse y compilarse la especificacin sin su cuerpo para posibilitar que otros sub-programas que referencian a estos elementos declarados puedan compilarse sin errores. De esta manera podremos armar un prototipo de nuestro sistema antes de codificar el detalle del mismo. Permite ocultar los detalles de implementacin Pueden especificarse cules tipos, variables y sub-programas dentro del paquete son pblicos (visibles y accesibles por otras aplicaciones y sub-programas fuera del paquete) o privados (ocultos e inaccesibles fuera del paquete). Por ejemplo, dentro del paquete pueden existir procedimientos y funciones que sern invocados por otros programas, as como tambin otras rutinas de uso interno del paquete que no tendrn posibilidad de ser accedidas fuera del mismo. Esto asegura que cualquier cambio en la definicin de estas rutinas internas afectar slo al paquete donde se encuentran, simplificando el mantenimiento y protegiendo la integridad del conjunto. Agrega mayor funcionalidad a nuestro desarrollo Las definiciones pblicas de tipos, variables y cursores hechas en la especificacin de un paquete persisten a lo largo de una sesin. Por lo tanto pueden ser compartidas por todos los sub-programas y/o paquetes que se ejecutan en ese entorno durante esa sesin. Por ejemplo, puede utilizarse esta tcnica (en dnde slo se define una especificacin de paquete y no un cuerpo) para mantener tipos y variables globales a todo el sistema. Introduce mejoras al rendimiento

En relacin a su ejecucin, cuando un procedimiento o funcin que est definido dentro de un paquete es llamado por primera vez, todo el paquete es ingresado a memoria. Por lo tanto, posteriores llamadas al mismo u otros sub-programas dentro de ese paquete realizarn un acceso a memoria en lugar de a disco. Esto no sucede con procedimientos y funciones estndares. Permite la Sobrecarga de funciones (Overloading). PL/SQL nos permite que varios procedimientos o funciones almacenadas, declaradas dentro de un mismo paquete, tengan el mismo nombre. Esto nos es muy til cuando necesitamos que los sub-programas puedan aceptar parmetros que contengan diferentes tipos de datos en diferentes instancias. En este caso Oracle ejecutar la versin de la funcin o procedimiento cuyo encabezado se corresponda con la lista de parmetros recibidos. Creacin del Cuerpo de un Paquete: Ejemplo 1: Definimos una funcin para validar la comisin. La comisin puede no ser mayor que la comisin ms alta entre todos los empleados. Tambin definimos un procedimiento que nos permite restablecer y validar la comisin que prevalece. SQL>CREATE OR REPLACE PACKAGE BODY comm_package IS FUNCTION validate_comm (v_comm IN NUMBER) RETURN BOOLEAN IS v_max_comm NUMBER; BEGIN SELECT MAX(comm) INTO v_max_comm FROM emp; IF v_comm > v_max_comm THEN RETURN(FALSE); ELSE RETURN(TRUE); END IF; END validate_comm; END comm_package; / Ejemplo 2: SQL>PROCEDURE reset_comm (v_comm IN NUMBER) IS v_valid BOOLEAN; BEGIN v_valid := validate_comm(v_comm); IF v_valid = TRUE THEN g_comm := v_comm; ELSE RAISE_APPLICATION_ERROR

(-20210,'Invalid commission'); END IF; END reset_comm; END comm_package; / Llamada a Programas de un Paquete Despus que se almacena el paquete en la base de datos, podemos invocar un programa dentro del paquete o desde fuera del mismo, dependiendo de si el programa es pblico o privado. Cuando llamamos a un procedimiento o funcin dentro del paquete, no necesitamos modificar su nombre. Ejemplo 1: Llamada a una funcin desde un procedimiento del mismo paquete: Llamamos a la funcin VALIDATE_COMM desde el procedimiento RESET_COMM. Cuando llamamos a un procedimiento o funcin desde fuera del paquete, debemos modificar su nombre con el nombre del paquete. CREATE OR REPLACE PACKAGE BODY comm_package IS ... PROCEDURE reset_comm(v_comm IN NUMBER) IS v_valid BOOLEAN; BEGIN v_valid := validate_comm(v_comm); IF v_valid = TRUE THEN g_comm := v_comm; ELSE RAISE_APPLICATION_ERROR (-20210, 'Invalid comm'); END IF; END reset_comm; END comm_package;
Ejemplo 2

Llamamos al procedimiento RESET_COMM desde SQL*Plus, haciendo prevalecer la comisin $1500 en la sesin del usuario. SQL>EXECUTE comm_package.reset_comm(1500); Ejemplo 3 Desde SQL*Plus llamamos al procedimiento RESET_COMM que se encuentra en el esquema scott, haciendo prevalecer la comisin $ 1500 en la sesin del usuario. SQL> EXECUTE scott.comm_package.reset_comm(1500);

Ejemplo 4 Llamamos al procedimiento RESET_COMM que se encuentra situado en una base de datos remota, que est determinado por el enlace de base de datos nombrado por SQL*Plus, haciendo prevalecer la comisin $ 1500 en la sesin del usuario. Adherirse a las convenciones de nombrado normales para llamar a un procedimiento en un esquema diferente, o en una base de datos diferente de otro nodo.
SQL>

EXECUTE comm_package.reset_comm@ny (1500);

Triggers Un trigger o disparador se ejecuta ante un determinado evento de manera automtica. Generalmente se utilizan para garantizar que una determinada accin siempre se realiza despus de realizar una tarea determinada. Se debe tener cuidado con este tipo de estructuras puesto que un uso excesivo puede dar lugar a dependencias difciles de mantener. Adems se deben tener muy claros las restricciones de integridad para evitar problemas. La sintaxis sera A nivel de sentencia: CREATE [OR REPLACE] TRIGGER nombre_trigger momento_ejecucin evento [evento] ON nombre_tabla bloque PLSQL; A nivel de registro: CREATE [OR REPLACE] TRIGGER nombre_trigger momento_ejecucin evento [evento] ON nombre_tabla [REFERENCING OLD AS old | NEW AS new] FOR EACH ROW [WHEN condicin] bloque PLSQL; Donde "momento_ejecucin" indica cuando se ejecuta el trigger automticamente. Puede contener los valores BEFORE AFTER. "evento" indica la operacin que provoca la ejecucin de este bloque. Puede contener los valores INSERT, UPDATE DELETE. "old" indica el nombre que se le da al registro con los valores antiguos que se tenan antes de la ejecucin de la operacin que activ el trigger. Mientras que "new" indica el valor que tiene actualmente despus de dicha operacin.

Con la clusula "WHEN" se puede indicar una restriccin que haga que el trigger se ejecute o no. Por ejemplo se puede indicar que el trigger se ejecute solo si el campo "campo1" de la tabla tiene un valor mayor que 50. La clusula "FOR EACH ROW" indica que el trigger es a nivel de registro. Para eliminar un trigger: DROP TRIGGER nombre_trigger

Ejemplo: BEFORE Statement: Ejemplo: Podemos crear un trigger BEFORE Statement con el fin de prevenir q ue suceda la operacin del trigger si se viola cierta condicin. Creamos un disparador para restringir las inserciones en la tabla EMP a ciertas horas, de Lunes a Viernes. Si un usuario intenta insertar un registro en la tabla EMP en Sbado, por ejemplo, el usuario ver el mensaje, fallar el trigger y se har rollback sobre las sentencias del Trigger. RAISE_APPLICATION_ERROR es un procedimiento que imprime un mensaje para el usuario y provoca que falle el bloque PL/SQL. Cuando falla un trigger de la base de datos, Oracle Server hace rollback sobre las sentencias del trigger. SQL> CREATE OR REPLACE TRIGGER secure_emp BEFORE INSERT ON emp BEGIN IF (TO_CHAR (sysdate,'DY') IN ('SAT','SUN')) OR (TO_CHAR(sysdate,'HH24')NOT BETWEEN '08' AND '18' THEN RAISE_APPLICATION_ERROR (-20500, 'You may only insert into EMP during normal hours.'); END IF; END; / Ejemplo Intentar insertar un registro en la tabla EMP fuera de horas de trabajo. SQL> INSERT INTO emp (empno, ename, deptno) 2 VALUES (7777, 'BAUWENS', 40); INSERT INTO emp (empno, ename, deptno) *

ERROR at line 1: ORA-20500: You may only insert into EMP during normal hours. ORA-06512: at "SCOTT.SECURE_EMP", line 4 ORA-04088: error during execution of trigger 'SCOTT.SECURE_EMP' Trigger After Statement: Ejemplo Crear una un trigger AFTER statement con el fin de auditar la operacin de trigger o realizar un clculo despus que se ha completado una operacin. Supongamos que tenemos una tabla de auditoria definida por el usuario (ver pgina siguiente) que relaciona los usuarios y cuenta sus operaciones de manipulacin de datos. Despus de que cualquier usuario haya actualizado la columna SAL en la tabla EMP, utilizaremos la tabla de auditoria para asegurarnos de que el nmero de cambios del sueldo no excede del mximo permitido para ese usuario. SQL>CREATE OR REPLACE TRIGGER check_salary_count AFTER UPDATE OF sal ON emp DECLARE v_salary_changes NUMBER; v_max_changes NUMBER; BEGIN SELECT upd, max_upd INTO v_salary_changes, v_max_changes FROM audit_table WHERE user_name = user AND table_name = 'EMP' AND column_name = 'SAL'; IF v_salary_changes > v_max_changes THEN RAISE_APPLICATION_ERROR (-20501, 'You may only make a maximum of '|| TO_CHAR (v_max_changes) || ' changes to the SAL column'); END IF; END; / Trigger After Row: Ejemplo Crear un trigger de registro para mantenter un contador de las operaciones de manipulacin de datos en las tablas de la base de datos por diferentes usuarios. Si la rutina de un trigger no tiene lugar antes de la operacin de trigger, crear un trigger AFTER row en lugar de un trigger BEFORE row.

SQL>CREATE OR REPLACE TRIGGER audit_emp AFTER DELETE OR INSERT OR UPDATE ON emp FOR EACH ROW BEGIN IF DELETING THEN UPDATE audit_table SET del = del + 1 WHERE user_name = user AND table_name = 'EMP' AND column_name IS NULL; ELSIF INSERTING THEN UPDATE audit_table SET ins = ins + 1 WHERE user_name = user AND table_name = 'EMP' AND column_name IS NULL; ELSIF UPDATING ('SAL') THEN UPDATE audit_table SET upd = upd + 1 WHERE user_name = user AND table_name = 'EMP' AND column_name = 'SAL'; ELSE /* The data manipulation operation is a general UPDATE. */ UPDATE audit_table SET upd = upd + 1 WHERE user_name = user AND table_name = 'EMP' AND column_name IS NULL; END IF; END; / Uso de los calificadores OLD y NEW: Ejemplo Crear un trigger sobre la tabla EMP para aadir registros a la tabla de auditora, AUDIT_EMP_VALUES, que contiene la actividad del usuario contra la tabla EMP. El trigger registra los valores de varias columnas antes y despus del cambio de datos utilizando calificadores OLD y NEW con el respectivo nombre de columna. SQL>CREATE OR REPLACE TRIGGER audit_emp_values AFTER DELETE OR INSERT OR UPDATE ON emp FOR EACH ROW BEGIN INSERT INTO audit_emp_values (user_name, timestamp, id, old_last_name, new_last_name, old_title, new_title, old_salary, new_salary) VALUES (USER, SYSDATE, :old.empno, :old.ename, :new.ename, :old.job, :new.job, :old.sal, :new.sal); END; /

Cursores Un cursor es el nombre para un rea memoria privada que contiene informacin procedente de la ejecucin de una sentencia SELECT. Cada cursor tiene unos atributos que nos devuelven informacin til sobre el estado del cursor en la ejecucin de la sentencia SQL. Cuando un

cursor est abierto y los datos referenciados por la consulta SELECT cambian, estos cambios no son recogidos por el cursor. PL/SQL crea implcitamente un cursor para todas las sentencias SQL de manipulacin de datos sobre un conjunto de filas, incluyendo aquellas que solo devuelven una sola fila. En PL/SQL no se pueden utilizar sentencias SELECT de sintaxis bsica ( SELECT FROM ). PL/SQL utiliza cursores para gestionar las instrucciones SELECT. Un cursor es un conjunto de registros devuelto por una instruccin SQL. Podemos distinguir dos tipos de cursores:

Cursores implcitos. Este tipo de cursores se utiliza para operaciones SELECT INTO. Se usan cuando la consulta devuelve un nico registro. Cursores explcitos. Son los cursores que son declarados y controlados por el programador. Se utilizan cuando la consulta devuelve un conjunto de registros. Ocasionalmente tambin se utilizan en consultas que devuelven un nico registro por razones de eficiencia. Son ms rpidos.

Un cursor se define como cualquier otra variable de PL/SQL y debe nombrarse de acuerdo a los mismos convenios que cualquier otra variable. Los cursores implcitos se utilizan para realizar consultas SELECT que devuelven un nico registro. Deben tenerse en cuenta los siguientes puntos cuando se utilizan cursores implcitos:

Los cursores implcitos no deben ser declarados Con cada cursor implcito debe existir la palabra clave INTO. Las variables que reciben los datos devueltos por el cursor tienen que contener el mismo tipo de dato que las columnas de la tabla. Los cursores implcitos solo pueden devolver una nica fila. En caso de que se devuelva ms de una fila (o ninguna fila) se producir una excepcin. Las ms comunes son:

NO_DATA_FOUND: Se produce cuando una sentencia SELECT intenta recuperar datos pero ninguna fila satisface sus condiciones. Es decir, cuando no hay datos TOO_MANY_ROWS Dado que cada cursor implcito slo es capaz de recuperar una fila, esta excepcin detecta la existencia de ms de una fila. SET SERVEROUTPUT ON; declare vdescripcion VARCHAR2(50); begin SELECT DESCRIPCION INTO vdescripcion from PAISES WHERE CO_PAIS = 'ESP'; dbms_output.put_line('La lectura del cursor es: ' || vdescripcion); end; Para procesar instrucciones SELECT que devuelvan ms de una fila, son necesarios cursores explcitos combinados con una estructura de bloque. A partir de ahora, cuando hagamos referencia a cursores nos referiremos a cursores explcitos.

Para trabajar con un cursor hay que realizar los siguientes pasos: 1. 2. 3. 4. Declarar el cursor Abrir el cursor en el servidor Recuperar cada una de sus filas (bucle) Cerrar el cursor

1. Declarar el cursor Al igual que cualquier otra variable, el cursor se declara en la seccin DECLARE. Se define el nombre que tendr el cursor y qu consulta SELECT ejecutar. No es ms que una declaracin. La sintaxis bsica es: CURSOR nombre_cursor IS instruccin_SELECT CURSOR nombre_cursor(param1 tipo1, ..., paramN tipoN) IS instruccin_SELECT Una vez que el cursor est declarado ya podr ser utilizado dentro del bloque de cdigo. Antes de utilizar un cursor se debe abrir. En ese momento se ejecuta la sentencia SELECT asociada y se almacena el resultado en el rea de contexto (estructura interna de memoria que maneja el cursor). Un puntero seala a la primera fila 2. Abrir el cursor Al abrir el cursor se ejecuta la sentencia SELECT asociada y cuyo resultado se guarda en el servidor en un rea de memoria interna (tablas temporales) de las cuales se va retornando cada una de las filas segn se va pidiendo desde el cliente. Al abrir un cursor, un puntero sealar al primer registro. La sintaxis de apertura de un cursor es: OPEN nombre_cursor; OPEN nombre_cursor(valor1, valor2, ..., valorN); Una vez que el cursor est abierto, se podr empezar a pedir los resultados al servidor. 3. Recuperar cada una de sus filas. Una vez que el cursor est abierto en el servidor se podr hacer la peticin de recuperacin de fila. En cada recuperacin solo se acceder a una nica fila. La sintaxis de recuperacin de fila de un cursor es: FETCH nombre_cursor INTO variables; Podremos recuperar filas mientras la consulta SELECT tenga filas pendientes de recuperar. Para saber cundo no hay ms filas podemos consultar los siguientes atributos de un cursor:

Al recuperar un registro, la informacin recuperada se guarda en una o varias variables. Si slo se hace referencia a una variable, sta se puede declarar con %ROWTYPE. Si se utiliza una lista de variables, cada variable debe coincidir en tipo y orden con cada una de las columnas de la sentencia SELECT. As lo accin ms tpica es recuperar filas mientras queden alguna por recuperar en el servidor. Esto lo podremos hacer a travs de los siguientes bloques: OPEN nombre_cursor; LOOP FETCH nombre_cursor INTO variables; EXIT WHEN nombre_cursor%NOTFOUND; --procesar cada una de las filas END LOOP; OPEN nombre_cursor; FETCH nombre_cursor INTO lista_variables; WHILE nombre_cursor%FOUND LOOP /* Procesamiento de los registros recuperados */ FETCH nombre_cursor INTO lista_variables; END LOOP; CLOSE nombre_cursor;

FOR variable IN nombre_cursor LOOP /* Procesamiento de los registros recuperados */ END LOOP;

4. Cerrar el cursor Una vez que se han recuperado todas las filas del cursor, hay que cerrarlo para que se liberen de la memoria del servidor los objetos temporales creados. Si no cerrsemos el cursor, la tabla temporal quedara en el servidor almacenada con el nombre dado al cursor y la siguiente vez ejecutsemos ese bloque de cdigo, nos dara la excepcin CURSOR_ALREADY_OPEN (cursor ya abierto) cuando intentsemos abrir el cursor. Para cerrar el cursor se utiliza la siguiente sintaxis: CLOSE numbre_cursor;

Cuando trabajamos con cursores debemos considerar:

Cuando un cursor est cerrado, no se puede leer. Cuando leemos un cursor debemos comprobar el resultado de la lectura utilizando los atributos de los cursores. Cuando se cierra el cursor, es ilegal tratar de usarlo. El nombre del cursor es un identificador, no una variable. Se utiliza para identificar la consulta, por eso no se puede utilizar en expresiones.

Atributos en cursores implcitos Los cursores implcitos no se pueden manipular por el usuario, pero Oracle s permite el uso de sus atributos. Las sentencia a travs de las que podemos obtener informacin de estos atributos son: SELECTINTO, INSERT, UPDATE, DELETE. En este caso, se debe anteponer al nombre del atributo el prefijo SQL, en lugar del nombre del cursor.

SQL%NOTFOUND devuelve TRUE cuando la ltima sentencia SELECT no recuper ninguna fila, o cuando INSERT, DELETE o UPDATE no afectan a ninguna fila SQL%FOUND devuelve TRUE cuando la ltima sentencia SELECT devuelve alguna fila, o cuando INSERT, DELETE o UPDATE afectan a alguna fila SQL%ROWCOUNT devuelve el nmero de filas afectadas por INSERT, DELETE o UPDATE o las filas devueltas por una sentencia SELECT SQL%ISOPEN siempre devuelve FALSE, porque Oracle cierra automticamente el cursor implcito cuando termina la ejecucin de la sentencia SELECT

Ejemplos: DECLARE CURSOR cpaises IS SELECT CO_PAIS, DESCRIPCION, CONTINENTE FROM PAISES; co_pais VARCHAR2(3); descripcion VARCHAR2(50); continente VARCHAR2(25); BEGIN OPEN cpaises; FETCH cpaises INTO co_pais,descripcion,continente; DBMS_OUTPUT.PUT_LINE(continente); CLOSE cpaises; END;

DECLARE CURSOR cpaises IS

SELECT CO_PAIS, DESCRIPCION, CONTINENTE FROM PAISES; registro cpaises%ROWTYPE; BEGIN OPEN cpaises; FETCH cpaises INTO registro; DBMS_OUTPUT.PUT_LINE(continente); CLOSE cpaises; END;

DECLARE r ARTICULOS%ROWTYPE; BEGIN FOR r IN ( SELECT * FROM ARTICULOS ) LOOP DBMS_OUTPUT.PUT_LINE(r.cArtDsc); END LOOP; END; BEGIN UPDATE ARTICULOS SET cArtDsc = `Pantalla LCD WHERE cCodArt = LCD; IF SQL%NOTFOUND THEN -- Otra opcin : SQL%ROWCOUNT = 0 INSERT INTO ARTICULOS (cCodArt,cDesArt) VALUES (LCD,Pantalla LCD); END IF; END; Cursores Parametrizados Los cursores son aquellos que permiten utilizar la orden OPEN para pasarle al cursor el valor de uno o varios de sus parmetros. DECLARE CURSOR cArt (cFml Articulos.cArtFml%TYPE) IS SELECT cArtCdg,cArtDsc FROM Articulos WHERE cArtFml = cFml; xCod Articulos.cArtCdg%TYPE; xDes Articulos.cArtDsc%TYPE;

BEGIN OPEN cArt('F1'); LOOP FETCH cArt INTO xCod,xDes; EXIT WHEN cArt%NOTFOUND; DBMS_OUTPUT.PUT_LINE (xDes); END LOOP; CLOSE cArt; END; Cursores de actualizacin Los cursores de actualizacin se declaran igual que los cursores explcitos, aadiendo FOR UPDATE al final de la sentencia SELECT. CURSOR nombre_cursor IS instruccin_SELECT FOR UPDATE

Para actualizar los datos del cursor hay que ejecutar una sentencia UPDATE especificando la clusula WHERE CURRENT OF. UPDATE SET = [, = ] WHERE CURRENT OF Cuando trabajamos con cursores de actualizacin debemos tener en cuenta que la sentencia UPDATE genera bloqueos en la base de datos ( transacciones, disparadores,etc). DECLARE CURSOR cpaises IS select CO_PAIS, DESCRIPCION, CONTINENTE from paises FOR UPDATE; co_pais VARCHAR2(3); descripcion VARCHAR2(50); continente VARCHAR2(25); BEGIN OPEN cpaises; FETCH cpaises INTO co_pais,descripcion,continente; WHILE cpaises%found LOOP

UPDATE PAISES SET CONTINENTE = CONTINENTE || '.' WHERE CURRENT OF cpaises; FETCH cpaises INTO co_pais,descripcion,continente; END LOOP; CLOSE cpaises; COMMIT; END;

También podría gustarte