Manual Pl SQL

March 27, 2018 | Author: sergiokuro | Category: Pl/Sql, Sql, Programming Language, Table (Database), Areas Of Computer Science


Comments



Description

PL/SQLIntroducción Qué es el lenguaje PL/SQL y primeras explicaciones para saber cómo funciona este gestor PL/SQL. Nos encontramos ante un gestor que va incorporado en Oracle para solventar las grandes limitaciones que teníamos con los editores SQL, en cuanto al control de las secuencias de ejecución de instrucciones, el uso de variables, la gestión de posibles errores, etc. Este lenguaje esta basado en ADA, por lo que incluye todas las características de los lenguajes de tercera generación. Esto nos permite manejar las variables, tener una estructura modular (procedimientos y funciones) y controlar las excepciones. Además incorpora un completo soporte para la programación orientada a objetos (POO). Los programas creados con PL/SQL los podemos almacenar en nuestra base de datos como cualquier otro objeto quedando disponibles para los usuarios. El uso del lenguaje PL/SQL es imprescindible para construir disparadores de bases de datos (triggers). PL/SQL esta incluido en el servidor y en algunas herramientas de cliente. Soporta todos los comandos de consulta y manipulación de datos, aportando al lenguaje SQL las estructuras de control y otros elementos propios de los lenguajes de programación de 3º generación. La unidad de trabajo en PL/SQL es el bloque, constituido por un conjunto de declaraciones, instrucciones y mecanismos de gestión de errores y excepciones. Bloques Con PL/SQL se pueden construir distintos tipos de programas: procedimientos, funciones y bloques anónimos, paquetes, etc. Todos ellos tienen en común una estructura básica denominada bloque. Un bloque tiene 3 zonas: Zona de declaraciones: donde se declaran objectos locales. Suele ir precedida por la cláusula declare (o is o as en los procedimientos y funciones). Un conjunto de instrucciones precedido por la cláusula BEGIN Zona de excepciones: es una zona opcional precedida por la cláusula EXCEPTION, donde se gestionan las excepciones. El formato genérico de un bloque es el siguiente: [ DECLARE <declaraciones>] BEGIN <instrucciones> [EXCEPTION <gestión de excepciones>] END; Las únicas cláusulas obligatorias son BEGIN y END Antes de hacer ningún bloque tenemos que ejecutar el siguiente comando en nuestra ventana de Sql *PLUS set serveroutput on; Aunque ahora no entendáis mucho os dejo un ejemplo de un bloque para que os vayáis familiarizando con la sintaxis. DECLARE v_num_empleados number(2); BEGIN insert into depart values(99,'provisional',null); update emple set dept_no=99 where dept_no=20; v_num_empleados:=SQL%ROWCOUNT; delete from depart where dept_no=20 DBMS_OUTPUT.PUT_LINE (v_num_empleados || 'Empleados cambiados a provisional'); Ya en próximos artículos nos meteremos de lleno en la construcción de bloque y en entender las lineas arriba escritas. Características de PL/SQL primera parte Para poder trabajar con PL/SQL tenemos que tener claros una serie de conceptos y definiciones sobre todo en lo referente a compatibilidad de datos y estructuras de control. Definición de datos compatibles con SQL Este lenguaje suele tener unos tipos de datos compatibles con SQL para las columnas de las tablas, pero además puede tener otros tipos de datos propios. Para declarar los datos en un bloque tenemos que utilizar una sintaxis como esta: DECLARE nombre_variable Tipo dato; BEGIN ... Un ejemplo seria este: DECLARE precio NUMBER(8,2); suma NUMBER(2) DEFAULT 0; prenda CHAR(20) NOT NULL :='Camiseta'; descripción VARCHAR2(15); BEGIN .... Una de las ventajas de PL/SQL es que nos permite declarar una variable del mismo tipo que otra variable o que una columna de una tabla. Esto lo hacemos con el atributo %TYPE. DECLARE nombre emple.nombre%TYPE; Otra ventaja es que nos permite guardar el contenido de una fila entera de una tabla en una variable. Esto lo hacemos con el atributo %ROWTYPE DECLARE mifila emple%ROWTYPE; Con esto ya podemos trabajar con variables dentro de nuestro bloque. Ahora tenemos que ver las estructuras de control que podemos manejar dentro de nuestros bloques. Estructuras de control Las estructuras de control son básicamente las mismas que podemos utilizar en cualquier lenguaje de programación. La vamos a dividir en estructuras de control alternativas (IF) y estructuras de control repetitivas (WHILE, FOR, LOOP) La estructura del IF seria la siguiente: IF <condición> THEN instrucciones ELSEIF <condición> THEN instrucciones .... ELSE instrucciones END IF; La estructura del WHILE seria la siguiente: WHILE <condición> LOOP instrucciones END LOOP; La estructura del FOR se escribiría así: FOR <variable> IN <mínimo> <máximo> LOOP instrucciones END LOOP Si queremos que nos vaya contando al revés, es decir de 5 hasta 0 por ejemplo, la sintaxis seria la siguiente: FOR <variable> IN REVERSE <final>.......<inicio> LOOP instrucciones ..... END LOOP; Y la estructura del LOOP seria de esta forma: LOOP instrucciones .... EXIT WHEN <condición> instrucciones ... END LOOP; Cursores implicitos Es importante saber que en nuestros bloques PL/SQL es bastante práctico el uso de cursores. En este lenguaje el resultado de una consulta no va directamente al terminal del usuario, sino que se guarda en un área de memoria a la que se accede mediante los nombrados cursores. Para realizar una consulta en PL/SQL tenemos que guardar el resultado en cursores. Esto es muy sencillo y basta con meter un INTO en las consultas. Un ejemplo seria este: select <columna/s> INTO <variable/s> from <tabla> [where] select count(*) INTO vnum from ventas; La variable que sigue al INTO recibe el valor de la columna. Por este motivo es importante que el tipo de dato de la variable coincida con el tipo de dato de la columna. Características de PL/SQL segunda parte Es importante controlar los posibles errores y además distinguir los distintos tipos de programas que podemos crear con PL/SQL. Gestión de excepciones Las excepciones sirven para tratar los errores y mensajes. Oracle tiene una serie de excepciones que son las más frecuentes y con las que la mayoría de la gente trabaja. Unas de las más usadas son: NO_DATA_FOUND (cuando una orden tipo select no ha devuelto ningún valor) TOO_MANY_ROWS (cuando una orden tipo select ha devuelto mas de una fila) OTHERS THEN RAISE_APPLICATION_ERROR (para cualquier otro tipo de error desconocido) Un ejemplo seria el siguiente: DECLARE vapellido varchar(10); voficio varchar(20); BEGIN select apellido,oficio INTO vape,voficio from emple where emp=15; DBMS_OUTPUT.PUT_LINE (vape||: - || voficio); EXCEPTION WHEN NO_DATA_FOUND THEN insert into temp values('No hay datos'); WHEN TOO_MANY_ROWS THEN insert into temp values ('Demasiados datos'); WHEN OTHER THEN RAISE_APPLICATION_ERROR(-2000,'Error en aplicación'); END; Estructura modular En PL/SQL podemos distinguir 3 tipos de programas o bloques. Bloques anónimos: Son los que no tienen nombre y comienzan con el DECLARE, es decir los que hemos ido viendo hasta ahora. Procedimientos: Se trata del programa más utilizado en PL/SQL y su formato es el siguiente: PROCEDURE <nombre_procedimiento> [(<lista de parámetros>)] IS [<declaraciones>] BEGIN <instrucciones>; [EXCEPTIONS <excepciones>;] END; En el formato distinguimos dos partes claramente, la cabecera donde esta el nombre del procedimiento y los parámetros y el cuerpo donde se situá un bloque anónimo. Funciones: similares a los procedimientos pero con la función añadida de que pueden devolver valores. Si subís varias lineas y veis el ejemplo de control de excepciones, podéis ver que hemos utilizado un atributo como DBMS_OUTPUT. Bien pues esto lo que nos permite es visualizar en pantalla los resultados, tanto excepciones como mensajes. Lo utilizamos porque PL/SQL no dispone de ordenes o sentencias que capturen datos introducidos por teclado, ni tampoco para visualizar datos en pantalla. DBMS_OUTPUT.PUT_LINE nos permite visualizar en pantalla, pero para que funcione correctamente tenemos que poner el SET SERVEROUTPUT a ON Si queremos que un bloque nos pida algún dato tenemos que anteponer el símbolo & delante de la variable, de esta forma cuando el bloque llegue a ese punto nos pedirá por pantalla el valor. Otra sentencia importante es la que nos permite visualizar los errores que hemos podido tener al crear el bloque o procedimiento. Esta sentencia es: show errors Podemos agregar comentarios a nuestros bloques anteponiendo al comentario “/* <comentario> */” Si queremos que el bloque anónimo se ejecute directamente cuando terminamos de crearlo debemos poner el símbolo / que, ademas de guardar el bloque en el buffer, lo ejecuta. También podemos guardar los bloques anónimos en ficheros para poderlos ejecutar posteriormente. Para ello ejecutamos la siguiente sentencia: save nombrefichero Y para ejecutarlo primero tenemos que cargar el fichero en el buffer y para ello tenemos que ejecutar la siguiente sentencia: get nombrefichero Una vez cargado el fichero ejecutamos el bloque con la sentencia run nombrefichero. O podemos hacer los dos pasos con una sola sentencia: start nombrefichero Sin embargo para los procedimientos es totalmente distinto ya que al tener nombre se almacena automáticamente en la base de datos y para ejecutarlo tan solo tenemos que realizar la siguiente operación: execute nombre_procedimiento(parámetros); En el siguiente capitulo revisaremos todo lo que hemos visto en la introducción del PL/SQL, pero de una forma mas exhaustiva. Bloques anónimos y procedimientos PL/SQL En este artículo vamos a ver el uso y ejemplos de los bloques anónimos en PL/SQL y los procedimientos. Para continuar las explicaciones sobre PL/SQL que estamos publicando en el Tutorial de Oraclede Desarrolloweb.com, veamos a continuación dos importantes elementos de esta plataforma. Bloques anónimos PL/SQL Empezaremos con los bloques anónimos, caracterizados porque no tienen nombre y se suelen crear y ejecutar desde PL/SQL. Todo bloque debe acabar en . para que sea almacenado en el buffer SQL. Una vez guardado lo podemos ejecutar con la orden “run”. También podemos guardarlo en un fichero con la siguiente orden: save nombrefichero [replace] El replace sólo lo pondremos si el fichero ya esta creado. Para cargar y ejecutar este bloque anónimo guardado en fichero ejecutaremos la siguiente orden: start nombrefichero El start lo podemos cambiar por la @ y nos funcionará igualmente. Pero también podemos cargarlo sin ejecutarlo con la orden “get” y luego ejecutarlo posteriormente con la orden “run” Un ejemplo muy sencillo de bloque seria el que nos muestra en pantalla un nombre. BEGIN DBMS_OUTPUT.PUT_LINE('nombre'); END; . Además en los bloques PL/SQL se pueden utilizar lo que llamamos variables de sustitución, que nos pedirán datos por pantalla antes de ejecutar el bloque. Estas variables tienen que ir antepuestas del & para que funcionen. Un ejemplo seria un bloque que nos pide el DNI de un usuario y nos muestra su nombre. DECLARE Vnom clientes.nombre%TYPE; BEGIN select nombre into Vnom from clientes where NIF= '&V_nif'; DBMS_OUTPUT.PUT_LINE (Vnom); END; . Como veis es bastante sencillo, pero no tienen tanta funcionalidad como los procedimientos o funciones. Procedimientos y funciones PL/SQL Los procedimientos y funciones quedan almacenados en la base de datos a diferencia de los bloques anónimos que se almacenaban en el buffer. Nota: Al quedar los bloques anónimos almacenados en el buffer, a no ser que se guardasen en ficheros, se perderían al limpiar el buffer, cosa que no ocurre con los procedimientos y funciones, que se almacenan en la propia base de datos. Otra cosa que nos diferencia los bloques anónimos de los procedimientos o funciones es que en los procedimientos o funciones no se pueden utilizar variables de sustitución. En cuanto a su construcción es la dada en el articulo Características de PL/SQL segunda parte añadiendo al principio la siguiente secuencia “CREATE OR REPLACE” para crearlo, o modificarlo si ya existe. Pasamos a escribir un procedimiento que nos muestre los datos de un usuario: CREATE OR REPLACE PROCEDURE ver_usuario(nomusu VARCHAR2) IS NIFusu VARCHAR2(10); Domusu VARCHAR2(10); BEGIN select nif, domicilio into NIFusu,Domusu from usuario where nombre=nomusu; DBMS_OUTPUT.PUT_LINE('Nombre:'||nomusu|| 'NIF:' ||NIFusu|| 'Domicilio' ||Domusu); EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('No hemos encontrado al usuario || nomusu); END; / Si el compilador detecta errores nos saldrá un mensaje como este: “Procedimiento creado con errores de compilación”. Para ver estos errores tenemos la orden SHOW ERRORS. Al tener almacenado el procedimiento en la base de datos, este puede ser llamado por cualquier usuario que tenga los permisos oportunos. Para invocar un procedimiento utilizamos la orden EXECUTE Para invocar al procedimiento que hemos creado antes tendríamos que ejecutar la siguiente orden: EXECUTE ver_usuario('Luis'); Pero también podemos invocarlo desde un bloque PL/SQL de ls siguiente forma: BEGIN ver_usuario('Luis'); END; . Como en cualquier lenguaje, podemos agregar comentarios a nuestros procedimientos de la siguiente forma: - - para comentar en una sola linea /* <comentario>*/ para varias lineas. Fundamentos del lenguaje PL/SQL En este artículo estudiaremos los fundamentos de PL/SQL y algunos de los elementos que constituyen este lenguaje. Para continuar con el manual de Oracle publicado en DesarrolloWeb.com, es hora de adentrarnos en las explicaciones de los elementos que forman parte del lenguaje PL/SQL. Tipos de datos Este lenguaje dispone de los mismo tipos de datos que podemos encontrar en SQL, pero además se han incorporado algunos nuevos:           char(n): almacena una cantidad fija de caracteres varchar2(n): almacena cadenas de caracteres de longitudes variables long(n): almacena cadenas de longitud variable number(p,e): almacena numero de precisión p y escala e boolean: almacena valores lógicos, true, false o NULL date: almacena fechas completas, incluida la hora raw(n): almacena datos binarios de longitud fija long raw : almacena datos binarios de longitud variable rowid: almacena identificadores de direcciones de fila etc. Además es importante señalar que el programador puede definir sus propios tipos de datos a partir de los ya definidos. Identificadores Se utilizan para nombrar los objetos que intervienen en los programas PL/SQL como son las variables, constantes, cursores, excepciones, procedimientos, etc. Pueden tener como máximo 30 caracteres empezando siempre por una letra, que puede ir seguida por otras letras, numeros, $, # ó _. Es importante destacar que PL/SQL no diferencia entre mayúsculas y minúsculas. También debemos señalar que no pueden contener espacios ni signos de puntuación. Variables Como doy por sentado que todos sabemos lo que son las variables, pasaremos directamente a comentar como se declara una variable en PL/SQL. <nombreVariable> <tipo> [NOT NULL] [{:= | DEFAULT } <valor>] No podemos indicar una lista de variables del mismo tipo y luego declarar el tipo, tenemos que hacerlo una a una. Uno ejemplo de declaración de variables seria el siguiente: DECLARE importe NUMBER (8,2); contador NUMBER(2'0); nombre char(5) NOT NULL :="Sara"; ... Uso de los atributos %TYPE y %ROWTYPE %TYPE: declara una variable del mismo tipo que otra, o que una columna de una tabla %ROWTYPE : crea una variable registro cuyos campos se corresponden con las columnas de una tabla o vista. Por ejemplo si tenemos una variable definida previamente llamada cantidad podemos definir otra de la siguiente forma: total cantidad%TYPE; De esta forma la variable total tendrá las mismas características que la variable cantidad. Otro ejemplo seria declarar una variable que fuera del mismo tipo que la columna nombre de la tabla profesor. nombre_alta nombre%ROWTYPE; Ámbito y visibilidad de variables La variable será local para el bloque en el que ha sido declarada y global para los bloque hijos de éste, mientras que las variables declaradas en los bloque hijos no son globales a los bloques padre. Constantes Cómo en la mayoría de los lenguajes, en este también podemos declaras constantes, de la siguiente forma: <nombreVariable> CONSTANT <tipo> := <valor>; Operadores Asignación := Lógicos AND OR NOT Concatenación || Is null = != <> < > <= >= between...and like in y sus correspondientes negaciones + - * / ** Comparación Aritméticos Funciones predefinidas En PL/SQL tenemos las mismas funciones predefinidas que en SQL (AVG, MIN, MAX, COUNT, SUM, etc), pero tenemos que tener dos cosas muy claras a la hora de utilizarlas y son: 1. La función no modifica el valor de las variables o expresiones que se pasan como argumentos, sino que devuelve un valor a partir de dicho argumento. 2. Si a una función se le pasa un valor nulo en la llamada, posiblemente devolverá un valor nulo. Etiquetas Podemos utilizar etiquetas para poder irnos a cualquier parte del programa utilizando la sentencia GOTO siempre y cuando se cumplan las siguientes reglas: No pueden haber etiquetas con los mismos nombres en un mismo programa. La etiqueta debe preceder a un bloque o a un conjunto de ordenes ejecutables la etiqueta no puede estar dentro de estructuras de control (IF, LOOP) Subprogramas PL/SQL Los subprogramas son los bloques PL/SQL con nombre que pueden recibir y devolver valores. En cualquier subprograma podemos distinguir:   La cabecera, compuesta por el nombre del subprograma, los parámetros y el tipo de valor de retorno. El cuerpo, compuesto por las declaraciones, las instrucciones y el manejo de excepciones. Podemos distinguir entre dos tipos de subprogramas, como ya hemos comentado en artículos anteriores: Procedimientos Los procedimientos ya los hemos visto en el articulo “Bloques anónimos y procedimientos PL/SQL ” por lo que pasamos directamente a las funciones. Funciones Las funciones son muy similares a los procedimiento con la diferencia que éstas siempre devolverán un valor. Su estructura es la siguiente: CREATE [OR REPLACE] FUNCTION NombreFuncion [(parámetros)] RETURN tipo IS [parte declarativa] BEGIN instrucciones RETURN <valor o expresión>; [EXCEPTION excepciones] END; La cláusula RETURN de la cabecera nos especifica el tipo de valor que nos va a devolver la función. Parámetros Todos los subprogramas utilizan parámetros para pasar y recibir información. Dentro de los parámetros podemos distinguir dos tipos:   Parámetros actuales: son variables indicadas en la llamada a un subprograma. Parámetros formales: son variables declaradas en la especificación del subprograma. Además podemos hacer el paso de parámetros de un tipo a otro. Generalmente si los tipos son compatibles PL/SQL lo hace automáticamente. En cualquier caso, podemos hacerlo de forma manual utilizando las siguientes notaciones:    Posicional: el compilador asocia los parámetros actuales a los formales, basándose en suposición. Nominal: el símbolo => después del parámetro actual y antes del nombre del formal, indica al compilador correspondencia. Mixta: nos permite usar las dos notaciones anteriores. Para que esto quede más claro pasamos a escribir un ejemplo de paso de parámetros y conversión de tipos. Tenemos la especificación de un procedimiento como esta: PROCEDURE departamento( n_departamento INTEGER, localidad VARCHAR2 IS... Desde el siguiente bloque se podrán realizar las llamadas indicadas: DECLARE num_departamento INTEGER; aula VARCHAR(30) BEGIN ... - - posicional departamento(num_departamento, aula); - - nominal departamento(num_departamento => n_departamento, aula =>localidad); ... END; Esto nos pasaría los parámetros num_departamento al mismo tipo que n_departamento y localidad al mismo tipo que aula. Los parámetros que soporta PL/SQL pueden ser de entrada, salida o entrada/salida Nos permite pasar valores a un subprograma. Dentro del subprograma, el parámetro actuá como una constante. Puede ser una variable, constante, literal o expresión. IN OUT Permite devolver valores al bloque que llamó al subprograma. Dentro del subprograma, el parámetro actúa como una variable no inicializada. Solo puede ser una variable. Permite pasar un valor inicial y devolver un valor actualizado. Dentro del IN subprograma, el parámetro actuá como variable inicializada. Puede intervenir OUT otras expresiones. El valor actual debe ser una variable. El formato genérico es el siguiente: <nombrevariable> [IN | OUT | IN OUT] <tipodato> [ { := | DEFAULT} <valor>] Además es importante recordar que al especificar parámetros debemos indicar el tipo, pero no el tamaño. Creación, modificación y borrado de subprogramas Cuando creamos subprogramas con SQL * PLUS utilizando los comandos CREATE, Oracle automáticamente compila el código fuente, genera el código objeto y los guarda en el diccionario de datos, quedando disponibles para su utilización. Para volver a compilar un subprograma almacenado utilizaremos la orden ALTER en vez del CREATE y su formato es el siguiente: ALTER {PROCEDURE | FUNCITON} nombresubprograma COMPILE; Para ver el código de un subprograma almacenado podemos ejecutar una sentencia como esta; select LINE, SUBSTR(TEXT,1,60) from USER_SOURCE where name = 'nombresubprograma'; Para borrar un subprograma almacenado utilizaremos la orden DROP de la siguiente forma: DROP {PROCEDURE | FUNCTION} nombresubprograma; Nota: PL/SQL implementa la recursividad en los subprogramas, esto quiere decir, que un programa puede llamarse a si mismo. Cursores en PL/SQL primera parte Comenzamos a explicar los cursores de PL/SQL. Veremos los cursores explícitos, sus atributos y las variables de acoplamiento . En los anteriores capítulos hemos visto los fundamentos del lenguaje PL/SQL, bien pues, a partir de ahora pasaremos a estudiar el manejo de este lenguaje para trabar con el gestor de Oracle. Empezaremos con la utilización de cursores. Hasta ahora hemos utilizado cursores implícitos, cuando devolvíamos el resultado de una select mediante la clausula into a una variable. Pero esto es un problema cuando el resultado de una subconsulta nos devolvía varias filas, porque esto nos daria un error al ejecutar la consulta Para que no nos salte un error en estos casos debemos utilizar los cursores explícitos. Cursores explícitos Los cursores explícitos los utilizamos cuando tenemos consultas que nos devuelven más de una fila. Tenemos 4 operaciones básicas para trabajar con un cursor explícito. 1. Declaración del cursor: lo tenemos que declarar en la zona de declaraciones, con el siguiente formato: CURSOR <nombrecursor> IS <sentencia SELECT>; 2. Apertura del cursor: Deberá colocarse en la zona de instrucciones, con el siguiente formato: OPEN <nombrecursor>; Al hacerlo se ejecuta automáticamente la sentencia select y sus resultados se almacenan en las estructuras internas de memoria manejadas por el cursor. 3. Recogida de información: Para recuperar la información anteriormente guardada en las estructuras de memoria interna tenemos que usar el siguiente formato: FETCH <nombrecursor> INTO {<variable> | <listavariables>}; Si tenemos una única variable que recoge los datos de todas las columnas, el formato de la variable seria el siguiente: <variable> <nombrecursor>%ROWTYPE; Si tenemos una lista de variables, cada una recogerá la columna correspondiente de la cláusula select, por lo que serán del mismo tipo que las columnas. 4. - Cierre del cursor: CLOSE <nombrecursor>; Ahora, veamos un ejemplo de utilización de cursores explícitos: DECLARE CURSOR C1 IS SELECT nombre, apellido FROM arbitro; Vnom VARCHAR2(12); Vape VARCHAR2(20); BEGIN OPEN C1; LOOP FETCH C1 INTO Vnom, Vape; EXIT WHEN C1%NOTFOUND; DBMS_OUTPUT.PUT_LINE(Vnom || '' || Vapen); END LOOP; CLOSE C1; END; Si nos fijamos, en la declaración de los cursores explícitos no utilizamos la cláusula INTO, que sí se utilizaba en los cursores implícitos. Ademas podéis ver que después del FETCH hemos comprobado si nos devuelve valores con la linea del EXIT. Es algo importante ya que si no nos devuelve nada el LOOP se interrumpirá. Atributos del cursor Para conocer detalles de la situación del cursor tenemos 4 atributos:     %FOUND: devuelve verdadero di el ultimo FETCH ha recuperado algún valor; en caso contrario devuelve falso; si el cursor no esta abierto nos devuelve error. %NOTFOUND: hace justamente lo contrario al anterior. %ROWCOUNT: nos devuelve el número de filas recuperadas hasta el momento. %ISOPEN: devuelve verdadero si el cursor esta abierto. Veamos ahora un ejemplo de utilización de %ROWCOUNT: DECLARE CURSOR C1 IS SELECT nombre from futbolista WHERE Cod='e1'; Vnom VARCHAR2(15); BEGIN OPEN C1; LOOP FETCH C1 INTO Vnom; EXIT WHEN C1%NOTFOUND; DBMS_OUTPUT.PUT_LINE (C1%ROWCOUNT || Vnom); END LOOP; CLOSE C1; END; Variables de acoplamientos en el manejo de cursores En el ejemplo siguiente podemos observar que en la cláusula WHERE se incluye una variable que se debería haber declarado previamente. Este tipo de variables reciben el nombre de variables de acoplamiento. El programa la sustituirá por su valor en el momento en que se abre el cursor, y se seleccionarán las filas según dicho valor. Aunque ese valor cambie durante la recuperación de los datos con FETCH, el conjunto de filas que contiene el cursor no variará. El ejemplo nos muestra los futbolistas de un equipo cualquiera. CREATE OR REPLACE PROCEDURE ver_futbolistas_por_equipos(codeq VARCHAR2) IS Vequi VARCHAR2(3); CURSOR C1 IS SELECT nombre from futbolista where codeq=Vequi; Vnom VARCHAR(15); BEGIN vequi:=codeq; OPEN C1; FETCH C1 INTO vnom; WHILE C1%FOUND LOOP DBMS_OUTPUT.PUT_LINE(Vnom); FETCH C1 INTO Vnom; END LOOP; CLOSE C1; END; Cursores PL/SQL segunda parte Continuamos con los cursores de PL/SQL, esta vez vamos a ver variables de acoplamiento y cursores con parámetros. Dando continuidad al Manual de Oracle que estamos publicando en DesarrolloWeb.com, y en el apartado del lenguaje PL/SQL, continuamos nuestras explicaciones sobre los cursores, que habíamos comenzado a explicar en el artículo anterior. Variables de acoplamiento Si os fijáis en el siguiente ejemplo veréis que en la cláusula where se incluye una variable que se deberá declarar previamente. Este tipo de variables recibe el nombre de variables de acoplamiento. El programa la sustituirá por su valor en el momento en que se abre el cursor, y se seleccionarán las filas según dicho valor. Create or replace procedure ver_jugador(codeq varchar2) IS vequi varchar2(3); cursor c1 is select nombre from jugador where cod=vequi; vnom varchar2(15); BEGIN vequi:=codeq; OPEN c1; FETCH c1 INTO vnom; WHILE c1%found LOOP DBMS_OUTPUT.PUT_LINE(vnom); FETCH c1 INTO vnom; END LOOP; CLOSE c1; END; Cursor FOR …. LOOP El trabajo normal de un cursor consiste en declarar un cursor, declarar una variable que recogerá los datos del cursor, abrir el cursor, recuperar con fetch, una a una, las filas extraídas introduciendo los datos en las variables, procesándolos y comprobando si se han recuperado datos o no. Para resumir todas esas tareas, tenemos una estructura cursor FOR...LOOP que hace todas estas cosas de forma implícita, todas menos la declaración del cursor. El formato y el uso de esta estructura es: 1. se declara la información cursor en la sección correspondiente 2. Se presenta el cursor utilizando el siguiente formato: FOR nombreVarReg IN nombreCursor LOOP …. END LOOP; Al entrar en el bucle se abre el cursor de manera automática, se declara implícitamente la variable nombreVarReg de tipo nombrecursor%ROWTYPE y se ejecuta el primer fetch cuyo resultado quedarán en nombreVarReg. A continuación se realizaran las acciones que correspondas hasta llegar al END LOOP. Este es un ejemplo del LOOP …. END LOOP: DECLARE cursor c2 is select nombre, peso, estatura from jugador where salario>1200; BEGIN FOR vreg IN c2 LOOP DBMS_OUTPUT.PUT_LINE (vreg.nombre || '-' ||vreg.peso || '-' || vreg.estatura); END LOOP; END; Cursores con parámetros Un cursor puede tener parámetros; en este caso se aplicara el siguiente formato genérico: CURSOR nombrecursor [(parámetros)] IS SELECT <sentencia select en la que intervendrán los parámetros>; Los parámetros formales indicados después del nombre del cursor tienen la siguiente sintaxis: nombreCursor [IN] tipodato [{:=|DEFAULT} valor] Todos los parámetros formales de un cursor son parámetros de entrada y su ámbito es local al cursor por eso sólo pueden ser referenciados dentro de la consulta. Un ejemplo seria el siguiente: DECLARE ... CURSOR C1 (vpeso number, vestatura number DEFAULT 170) is select nficha, nombre FROM emple WHERE estatura=vestatura AND peso=vpeso; Para abrir un cursor con parámetros lo haremos de la siguiente forma: OPEN nombrecursor [(parámetros)]; Cursores PL/SQL tercera parte Continuamos con los cursores, esta vez vamos a ver atributos con cursores explícitos y uso de cursores para actualizar filas. Atributos con Cursores implícitos Los atributos de los cursores implícitos que se crean son los siguientes:     SQL%NOTFOUND: nos dice si el último insert, update,delete o select into no han afectado a ninguna fila. SQL%FOUND: nos dice si el último insert, update,delete o select into ha afectado a una o mas filas SQL%ROWCOUNT: devuelve el número de filas afectadas por el último insert, update, delete o select into SQL%ISOPEN: Nos dice si el cursor esta cerrado, por lo que en teoría siempre nos dará falso ya que Oracle cierra automáticamente el cursor después de cada orden SQL. Es importante tener en cuenta una serie de cosas: Si se trata de un select into tenemos que tener en cuenta que solo puede devolver una única fila de lo contrario nos levantará automáticamente una de estas dos excepciones:  NO_DATA_FOUND: si la consulta no devuelve ninguna fila  TOO_MANY_ROWS: si la consulta devuelve más de una fila Cuando un select into hace referencia a una función de grupo nuca se levantará la excepción NO_DATA_FOUND y SQL%FOUND siempre será verdadero. Esto se explica porque las funciones de grupo siempre devuelven algún valor (NULL se considera un valor). Uso de cursores para actualizar filas Para realizar una actualización con un cursor tenemos que añadir la siguiente FOR UPDATE al final de la declaración del cursor: CURSOR nombre_cursor <declaraciones> FOR UPDATE Esto indica que las filas seleccionadas por el cursor van a ser actualizadas o borradas. Una vez declarado un cursor FOR UPDATE, se incluirá el especificador CURRENT OF nombre_cursor en la cláusula WHERE para actualizar o borrar la última fila recuperada mediante la orden FETCH. {UPDATE|DELETE}... WHERE CURRENT OF nombre_cursor. Os pongo un ejemplo para que quede claro: Subir el salario a todos los empleados del departamento indicado en la llamada. El porcentaje se indicará también en la llamada. CREATE OR REPLACE PROCEDURE subir_salario (num_dept NUMBER, incre NUMBER) IS CURSOR c IS SELECT oficio, salario FROM empleados WHERE cod_dept=num_dept FOR UPDATE; reg c%ROWTYPE; inc NUMBER (8); BEGIN OPEN c; FETCH c INTO reg; WHILE c%FOUND LOOP inc :=(reg.salario/100 )* inc; UPDATE empleados SET salario=salario+inc WHERE CURRENT OF c FETCH c INTO reg; END LOOP; END; También podemos usar ROWID en lugar de FOR UPDATE. ROWID nos indicará la fila que se va a actualizar. Para ello, al declarar el cursor en la cláusula SELECT indicaremos que seleccione también el identificador de fila: CURSOR nombre_cursor IS SELECT columna1,columna2,...ROWID FROM tabla; Al ejecutarse el FETCH se guardará el número de fila en una variable y después ese número se podrá usar en la cláusula WHERE de la actualización: {UPDATE |DELETE } ... WHERE ROWID = variable_rowid El ejemplo anterior utilizando ROWID quedaría de la siguiente manera: CREATE OR REPLACE PROCEDURE subir_salario (num_dept NUMBER, incre NUMBER) IS CURSOR c IS SELECT oficio, salario,ROWID FROM empleados WHERE cod_dept=num_dept FOR UPDATE; reg c%ROWTYPE; inc NUMBER (8); BEGIN OPEN c; FETCH c INTO reg; WHILE c%FOUND LOOP inc :=(reg.salario/100 )* inc; UPDATE empleados SET salario=salario+inc WHERE ROWID = reg.ROWID; FETCH c INTO reg; END LOOP; END; Con este artículo damos por terminado todo lo referente a cursores y empezamos a tratar las excepciones en el siguiente artículo. Excepciones en Oracle y PL/SQL Las excepciones en el sistema gestor Oracle y el lenguaje PL/SQL, nos ayudan a detectar y tratar errores en tiempo de ejecución. En este artículo del Manual de PL/SQL de Oracle vamos a ver lo que son las excepciones, para qué sirven y cómo utilizarlas. Daremos un repaso también a los tipos de excepciones, las excepciones definidas por el usuario y la sintaxis con la que tenemos que especificarlas. Por último, de paso que vemos cosas acerca del tratamiento de errores en PL/SQL, explicaremos el RAISE_APPLICATION_ERROR, un componente del sistema gestor de base de datos Oracle que ayuda a gestionar errores y sus mensajes de error. Qué son las excepciones en Oracle Las excepciones, presentes en la mayoría de los lenguajes de programación, sirven para tratar errores en tiempo de ejecución. En el sistema que nos ocupa, Oracle, sirven también para definir qué se debe hacer frente a errores en sentencias definidas por el usuario. Cuando se produce un error PL/SQL levanta una excepción y pasa el control a la sección excepción correspondiente al bloque PL/SQL. El formato sería el siguiente: BEGIN ......... ...... ...... EXCEPTION WHEN <nombre_excepción> THEN <instrucciones>; ...... [WHEN OTHERS THEN <instrucciones>;] END; Excepciones predefinidas Son aquellas que se disparan automáticamente al producirse determinados errores. Estas son las más comunes: too_many_rows: Se produce cuando select … into devuelve más de una fila. no_data_found: se produce cuando un select …. into no devuelve ninguna fila. login_denied: error cuando intentamos conectarnos a Oracle con un login y clave no validos. not_logged_on: se produce cuando intentamos acceder a la base de datos sin estar conectados. program_error: se produce cuando hay un problema interno en la ejecución del programa. value_error: se produce cuando hay un error aritmético o de conversión. zero_divide: se puede cuando hay una división entre 0. dupval_on_index: se crea cuando se intenta almacenar un valor que crearía duplicados en la clave primaria o en una columna con restricción UNIQUE. invalid_number: se produce cuando se intenta convertir una cadena a un valor numérico. Hay alguna más pero estas son las más utilizadas y tenemos que tener en cuenta que no es necesario declararlas en la sección DECLARE. Excepciones definidas por el usuario Son aquellas que crea el usuario. Para ello se requieren tres pasos: 1. Definición: se realiza en la zona de DECLARE con el siguiente formato: nombre_excepción EXCEPTION 2. Disparar o levantar la excepción mediante la orden raise: RAISE ; 3. Tratar la excepción en el apartado EXCEPTION: WHEN THEN ; Para que esto quede más claro ponemos un ejemplo a continuación. DECLARE ... Importe_mal EXCEPTION; ... BEGIN ... IF precio NOT BETWEEN mínimo and máximo THEN RAISE importe_mal; END IF; ... EXCEPTION WHEN importe_mal THEN DBMS_OUTPUT.PUT_LINE("Importe incorrecto"); ... END; Otras excepciones Existen otros errores internos de Oracle que no tienen asignada una excepción, sino un código de error y un mensaje, a los que se accede mediante funciones SQLCODE y SQLERRM. Cuando se produce un error de estos se trasfiere directamente el control a la sección EXCEPTION donde se tratara el error en la clausula WHEN OTHERS de la siguiente forma: WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Error'||SQLCODE||SQLERRM.) Utilización de RAISE_APPLICATION_ERROR En el paquete DBMS_STANDARD se incluye un procedimiento llamado RAISE_APPLICATION_ERROR que nos sirve para levantar errores y definir mensajes de error. Su formato es el siguiente: RAISE_APPLICATION_ERROR(numero_error,mensaje_error); Es importante saber que el numero de error esta comprendido entre -20000 y -20999 y el mensaje es una cadena de caracteres de hasta 512 bytes. Este procedimiento crea una excepción que solo puede ser tratada en WHEN OTHERS. Ponemos un ejemplo para que nos quede más claro. CREATE or REPLACE PROCEDURE subir_horas (emple NUMBER, horas_subir NUMBER) IS horas_actuales NUMBER; BEGIN Select horas into horas_actuales from empleados where id_empleado=emple; if horas_actuales is NULL then RAISE_APPLICATION_ERROR(-20010,'No tiene horas'); else update empleados set horas=horas_actuales + horas_subir where id_empleado=emple; end if; End subir_horas; Control de transacciones Control de transacciones en Oracle. Una transacción se define como un conjunto de operaciones sobre la base de datos. En Oracle si se ejecuta un conjunto de operaciones y una de ellas falla se aborta la transacción entera. En este artículo veremos todo lo que debemos saber sobre transacciones y algunos ejemplos interesantes. Está englogado dentro del Manual de Oracle que venimos publicando en DesarrolloWeb.com. La transacción finaliza cuando se ejecuta un comando de control de transacciones como rollback o commit work (se puede abreviar poniendo simplemente commit). Un ejemplo: BEGIN .... update alumnos set edad=20 where n_alumno=109; update nuevos set apellido='perez' where n_alumno=200; commit work; ... EXCEPTION WHEN OTHERS THEN rollback work; END; Comandos utilizados para el control de transacciones Commit Este comando da por concluida la transacción actual y hace definitivos los cambios realizados liberando las filas bloqueadas. Sólo después de que se ejecute commit tendremos acceso a los datos modificados. Rollback Este comando da por concluida la transacción actual y deshace los cambios que se pudiesen haber producido en la misma, liberando las filas bloqueadas. Se utiliza especialmente cuando no se puede concluir una transacción porque se han levantado excepciones. Savepoint Se utiliza para poner marcas o puntos de salvaguarda al procesar transacciones. Se utiliza junto con rollback permitiendo deshacer cambios hasta los savepoint. El número de savepoint esta limitado a 5 por sesión pero lo podemos modificar con la siguiente sentencia: savepoint numero; Rollback implicito Este comando se ejecuta cuando un programa almacenado (procedimiento o función) falla y no se controla la excepción que produjo el fallo. Pero si en el programa tenemos un commit estos cambios no serán deshechos. Rollback to Deshace el trabajo realizado después del punto indicado. Pero no se confirma el trabajo hecho hasta el savepoint. La transacción no finaliza hasta que se ejecuta un comando de control de transacciones o hasta que finaliza la sesión. Os dejo a continuación un ejemplo bastante completo de lo que seria el control de transacciones: create or replace procedure prueba (nfilas number) as begin savepoint ninguna; insert into tmp values ('primera fila'); savepoint una; insert into tmp values ('segunda fila'); savepoint dos; if nfilas=1 then rollback to una; else if nfilas=2 then rollback to dos; else rollback to ninguna; end if; commit; exception when other then rollback end prueba; Con este artículo terminamos la parte básica sobre oracle, PL/SQL y pasamos a lo que podemos denominar programación avanzada de sql. Empezaremos con triggers en el siguiente artículo. Triggers a tablas en PL/SQL Explicamos que son los triggers o disparadores de base de datos en PL/SQL de Oracle. Como ya comentábamos en el articulo anterior, publicado en el Manual de Oracle de DesarrolloWeb.com, comenzamos lo que podríamos denominar programación avanzada dentro de PL/SQL. En el presente artículo vamos a estudiar acerca de los triggers, donde veremos qué son y como se construyen, comenzando con los trigger de tablas y más tarde veremos los trigger de sustitución y los de sistema. Para ello lo primero que tenemos que ver es su definición. Trigger a tablas Un trigger es un bloque de código PL/SQL que se almacenan en la base de datos. Los bloques de código de los triggers están asociados a una tabla y se ejecutan automáticamente cuando se producen ciertos eventos asociados a la tabla. Se suelen utilizar para prevenir transacciones erróneas y nos sirven también para implementar restricciones de integridad o seguridad. Su formato básico es el siguiente: create or replace trigger nombre_trigger {before | after} {delete | insert | update[of lista_columnas]} [or {before | after} {delete|insert|update [of lista_columnas]}] on nombre_tabla [for each {row | statement | when (condición)}] /* comienza el trigger */ [declare] <declaraciones> begin <instrucciones> [exception] <excepciones> end; Elementos de un trigger before / after: elemento que dispara el trigger nombre: nombre del trigger que tiene que ser único. for each: nivel del disparo del trigger que por defecto es statement que significa que se dispara una sola vez por cada operación independientemente del número de filas afectadas. for each row: salta por cada fila afectada. Variables posibles para update: la primera es :old que hace referencia a los valores anteriores y :new que hace referencia a los nuevos valores de actualización de la fila. Tenemos que tener en cuanta unos cuantos aspectos:     Cuando el evento que dispara el trigger es un delete haremos referencia al valor :old porque el valor :new es nulo Cuando el evento que dispara el trigger es un insert haremos referencia al valor :new porque el :old es nulo. Cuando el evento es un update tiene sentido hacer referencia a los dos valores. Sólo se pueden utilizar cuando el trigger es a nivel de fila (for each row). Vamos a a crear un trigger que se disparé automáticamente después de la modificación del salario de la tabla empleado y pase un comentario a la tabla auditar. Create or replace trigger auditar_salario after update of salario on empleado for each row begin insert into auditar values ('se ha modificado el salario' || :old.num_empleado); end; Orden de ejecución de los trigger Una misma tabla puede tener varios triggers y el orden de disparo seria el siguiente: 1. Antes de comenzar a ejecutar la orden que provoca el disparo se ejecutaran los triggers del tipo before.... for each statement 2. Para cada fila afectada por la orden: a) se ejecutan los triggers del tipo before … for each row b) se ejecuta la actualización de la fila c) se ejecutan los triggers after... for each row 3. Una vez realizada la operación se ejecuta el after … for each statement Cuanndo se dispara un trigger este forma parte de la operación que lo disparó de manera que si el trigger falla, Oracle dará por fallida la operación completa. Aunque el fallo sea a nivel de fila se hará rollback a toda la operación. Ejemplo: create or replace trigger nombre_trigger before insert or delete begin if insert then ..... elseif deleting then .... elseif updating then ... end if .... end; En el siguiente articulo veremos los triggers de sustitución y los del sistema. Triggers de sustitución y de sistema Vemos lo que es un disparador de sustitución y el de sistema, así como su creación en Oracle. Disparadores de sustitución Podemos crear triggers que no se ejecutan antes ni después de una instrucción sino en lugar de (instead of). Solo podemos utilizar estos triggers si están asociados a vistas, además actúan siempre a nivel de fila. La sintaxis de este tipo de trigger es la siguiente: create [or replace] trigger nombre_trigger instead of { insert | delete | update [of columnas]} [ or { insert | delete | update}] on nombre vista [ for each row] [declare] declaraciones begin instrucciones [execption] excepciones end; Sobre una vista podemos hacer un select pero si hacemos un insert, delete o update puede darnos problemas y no dejar ejecutarse la orden correctamente. Los trigger sobre vistas vas a sustituir a estas operaciones por las correspondientes en las tablas que forman la vista. Un ejemplo de trigger de sustitución seria el siguiente: create or replace trigger t_borrado_emp instead of delete on empleado for each row begin delete from emple where emp_num=:old.cod end; Disparadores de sistema Estos trigger se disparan cuando se arranca o para la base de datos, entra o sale un usuario, cuando se crea, modifica o elimina un objeto, etc. En Oracle para crear este tipo de trigger tenemos que tener privilegios de Administer database trigger. La sintaxis de este trigger seria la siguiente: create [or replace] trigger nombre_trigger { before | after } { <lista eventos de definición> | <lista eventos del sistema>} on { database | schema} [when (condición)] <cuerpo del trigger (bloque PL/SQL)> Donde la lista de eventos de definición puede tener uno o más eventos DDL separados por or y la lista de eventos del sistema igualmente separados por or. Al asociar un disparador a un evento debemos indicar el momento en que se dispare. A continuación os dejo una tabla de evento, momento y cuando se dispararía para dejarlo todo mas o menos claro. Evento STARTUP SHUTDOWN LOGON LOGOFF Momento AFTER BEFORE AFTER BEFORE BEFORE | AFTER BEFORE | AFTER BEFORE | AFTER BEFORE | AFTER BEFORE | AFTER BEFORE | AFTER BEFORE | AFTER Se disparan: Después de arrancar la instancia Antes de apagar la istancia Después de que el usuario se conecte a la base de datos. Antes de la desconexión de un usuario Cuando ocurre un error en el servidor Antes o después de crear un objeto en el esquema Antes o después de borrar un objeto en el esquema Antes o después de cambiar un objeto en el esquema Antes o después de ejecutar un comando truncate Antes o después de ejecutar un comando grant Antes o después de ejecutar un comando revoke Antes o después de ejecutar cualquier comando de definición de datos SERVERERROR AFTER CREATE DROP ALTER TRUNCATE GRANT REVOKE DLL Oracle tiene algunas funciones que permiten acceder a los atributos del evento del disparo ORA_YSEVENT, ORA_LOGIN, etc. Estas funciones pueden usarse en la clausula WHEN o en el cuerpo del disparador. En el manual de Oracle podéis encontrar el listado de todas estas funciones. Un ejemplo seria un trigger que nos guarda los datos de un usuario al hacer login en la base de datos: create or replace trigger control after logon on database begin insert into control_conexion (usuario, momento, evento) values {ORA_LOGIN_USER, SYSTIMESTAMP, ORA_SYSEVENT); end; Documents Similar To Manual Pl SQLSkip carouselcarousel previouscarousel nextConsulta de base de datostarea 1 investigar conceptos.Introducción al lenguaje PLSQLTema 08 - Consultas a Múltiples TablasPractica IndicesParciales DBA2SQL Embebido en CLes06102 - SQL 2008 - Transact-SQL News ESCURSO_SQLPa TriggersT-SQL Triggers Procedimientos AlmacenadosPara Imprimir SQLORACLE SQL DBA Leccion 06 (Español)Introduccion a Mysql267244240-Silabo-Final-2014-II-is-Vii-Ciclo.docxLabor at or Ion SQLModificacion de Bd08 Bases Datos VBNetOCWVJ1220Actividad2.6.OperadoresdeconjuntosysubconsultasAna Gabriela Mora Baltazar Materia m3s2Comandos de Administración de Base de DatosPractica Leccion 2Curso - SQL basicoTaller SQL Adsi 1441417Bases de Datos Sentencias SQLinformixEjercicio 2 DDL y DML ResoluciónSQL - ActualizacionIntegridad GDA-2012Clausulas de SQLFooter MenuBack To TopAboutAbout ScribdPressOur blogJoin our team!Contact UsJoin todayInvite FriendsGiftsLegalTermsPrivacyCopyrightSupportHelp / FAQAccessibilityPurchase helpAdChoicesPublishersSocial MediaCopyright © 2018 Scribd Inc. .Browse Books.Site Directory.Site Language: English中文EspañolالعربيةPortuguês日本語DeutschFrançaisTurkceРусский языкTiếng việtJęzyk polskiBahasa indonesiaSign up to vote on this titleUsefulNot usefulYou're Reading a Free PreviewDownloadClose DialogAre you sure?This action might not be possible to undo. Are you sure you want to continue?CANCELOK
Copyright © 2024 DOKUMEN.SITE Inc.