Laboratorios de BASES DE DATOS. (I.T. Informática) Gestor de bases de datos ORACLE M. Martínez, C. Hernández, C. Cuesta Dpto. de Informática (U. Valladolid)
Base de datos de ejemplo EMPLEADOS (NOMBRE, APELLIDOS, NSS, FNAC, DIRECCION, SEXO, SALARIO, SUPERNSS, DEPNO) DEPARTAMENTOS (NOMBRE, DEPNO, JEFENSS, FJEFE) LOCALIZACIONES (DEPNO, LOCALIDAD) PROYECTOS (NOMBRE, PROYNO, LOCALIDAD, DEPNO) TRABAJAR (NSS, PROYNO, HORAS) FAMILIARES (NSS, NOMBRE, SEXO, FNAC, RELACION) BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 2
Bloque 4 Triggers. JDBC. BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 3
Triggers (disparadores) Un trigger define una acción que se ejecuta cuando ocurre un cierto evento en la base de datos. Los triggers se utilizan para extender las restricciones en la base de datos o para supervisar los cambios que ocurren sobre los datos. Su ejecución es transparente para el usuario. Los triggers pueden referenciar tablas distintas de aquella cuyas modificaciones disparan el trigger. BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 4
Triggers Los tipos de eventos que se pueden supervisar con triggers son INSERT, DELETE o UPDATE. La ejecución del trigger puede ser BEFORE o AFTER del evento que lo dispara. Para crear un trigger sobre una tabla son necesarios privilegios de modificación sobre dicha tabla y de creación de triggers. El cuerpo del trigger (código que se ejecuta) consiste en bloques PL/SQL. BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 5
PL/SQL PL/SQL (Procedural Language/SQL) extiende SQL mediante construcciones propias de los lenguajes procedurales. La consecuencia es que se dispone de un lenguaje estructural más potente que SQL. La estructura básica es el bloque. Cada bloque ejecuta una acción. Los bloques se pueden anidar. BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 6
PL/SQL La estructura de un bloque PL/SQL es: DECLARE /* Declaración de variables, tipos y subprogramas */ BEGIN /* Sección ejecutable: procedimientos y sentencias SQL */ /* Esta es la única parte cuya aparición es obligatoria */ EXCEPTION /* Aquí va la manipulación de errores */ END; BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 7
Triggers. PL/SQL. Para ejecutar un programa PL/SQL, el texto del programa debe ir seguido de: una línea con un punto (. ), y una línea con run. BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 8
Triggers. Tipos. Los triggers se pueden clasificar en función del nivel en que se ejecutan: Row-Level:» La claúsula FOR EACH ROW especifica que el trigger se debe ejecutar para cada fila afectada por el evento. Statement-Level:» De no incluirla, el trigger se ejecuta una única vez.» Se utilizan para reforzar la seguridad sobre los tipos de transacciones permitidos en las tablas. BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 9
Triggers Row-Level. Los triggers FOR EACH ROW pueden incluir una cláusula WHEN, que especifica una condición adicional que debe comprobarse antes de disparar el trigger. NO puede contener subconsultas. BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 10
Triggers. Tipos. Los triggers se pueden clasificar en función del momento en que se ejecuta: BEFORE:» Se ejecutan inmediatamente antes de la acción que los dispara. AFTER:» Se ejecutan inmediatamente después de la acción que los dispara. INSTEAD OF:» Se ejecutan en vez del evento que los dispara.» Sólo se pueden aplicar a vistas. BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 11
Triggers. Variables especiales. Las variables NEW y OLD están siempre disponibles para referirse a la nueva (después de la transacción) y vieja (previa a la transacción) tupla respectivamente. En el cuerpo del trigger, deben ir precedidas por dos puntos ( : ). Sin embargo, en la claúsula WHEN no es así.!! BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 12
Triggers. Creación. CREATE [OR REPLACE] TRIGGER <trigger_name> { BEFORE AFTER INSTEAD OF } { INSERT DELETE UPDATE [OF <column> [,<column>]...] } ON {<table> <view>} [ [REFERENCING { OLD AS <old_name> NEW AS <new_name>...] FOR EACH ROW [WHEN (<trigger_condition>)] ] <trigger_body> BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 13
Triggers. Creación. Dadas las tablas tabla1 y tabla2, insertar una tupla en tabla2 cada vez que se inserta en tabla1: CREATE TABLE TABLA1 (A INTEGER, B CHAR(10)); CREATE TABLE TABLA2 (C CHAR(10), D INTEGER);... CREATE TRIGGER trig1 AFTER INSERT ON TABLA1 FOR EACH ROW WHEN (NEW.a <= 10) BEGIN INSERT INTO TABLA2 VALUES (:NEW.b, :NEW.a); END trig1;. run; BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 14
Triggers. Restricciones específicas de ORACLE. ORACLE añade ciertas restricciones sobre los trigger_body: NO se puede modificar desde el trigger la misma tabla cuya modificación dispara el trigger. NO se puede modificar desde el trigger una tabla vinculada a la tabla del trigger por restricciones como las de clave foránea. BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 15
Triggers. Visualización y eliminación. Se puede obtener información sobre triggers en la tabla USER_TRIGGERS. select trigger_name from user_triggers; Los triggers pueden ser eliminados: drop trigger <trigger_name>; BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 16
Triggers. Visualización y eliminación. Los triggers pueden activarse/desactivarse: alter trigger <trigger_name> {disable enable}; alter table <table_name> enable all triggers; Es posible obtener los errores asociados con un trigger: show errors trigger <trigger_name>; BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 17
Triggers. Ejemplos. SQL> create trigger triggeruno 2 after insert on tabla1 3 begin 4 insert into tabla2 values ( T_mod, :new.a); 5 end; 6 / BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 18
Triggers. Ejemplos. SQL> create trigger triggeruno 2 after insert on tabla1 3 begin 4 insert into tabla2 values ( T_mod, 1); 5 end; 6 / BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 19
Triggers. Ejemplos. SQL> create trigger triggerdos 2 before insert or update of a on tabla1 3 for each row 4 begin 5 :new.a := :new.a * 166.386; 6 end; 7 / BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 20
Triggers. Ejemplos. SQL> create trigger triggerdos 2 before insert or update of a on tabla1 3 for each row 4 begin 5 :new.b := UPPER(:new.b); 6 end; 7 / BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 21
Triggers. Ejemplos. SQL> create trigger triggertres 2 before insert or update of a on tabla1 3 for each row 4 declare var char(1); 5 error_tipo EXCEPTION; 6 begin 7 select b into var 8 from tabla1 where b<> A ; 9 if var = D then 10 RAISE error_tipo; 11 end if; 12 EXCEPTION 13 WHEN error_tipo THEN 14 raise_application_error(-20001, Tipo D ); 15 end; 16 / BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 22
Triggers. Propuesta. Crear un trigger tal que, cada vez que se modifique el jefe de un departamento, se actualice convenientemente el dato JEFENSS en la tabla EMPLEADOS. (Nota: Crear previamente las tablas EMPLEADOS Y DEPARTAMENTOS) BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 23
Triggers. Propuesta. Crear un trigger tal que, cada vez que se modifique el jefe de un departamento, se actualice convenientemente el dato JEFENSS en la tabla EMPLEADOS. SQL> create trigger actualizar_jefe 2 before insert or update of jefenss on departamentos 3 for each row 4 begin 5 update empleados 6 set supernss = :new.jefenss 7 where supernss = :old.jefenss; 8 end; 9 / BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 24
Triggers. Propuesta. Crear un trigger que, cada vez que un empleado abandone la empresa, elimine los datos sobre sus familiares. BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 25
Triggers. Propuesta. Crear un trigger que, cada vez que un empleado abandone la empresa, elimine los datos sobre sus familiares. SQL> create trigger borrar_familiares 2 before delete on empleados 3 for each row 4 declare 5 emp number; 6 begin 7 emp := :old.nss; 8 delete from familiares 9 where nss = emp; 10 end; 11 / BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 26
Triggers. Ejemplos (1). create table pedidos { codigo number, precio number, nifproveedor varchar2(9) not null, descripcion varchar2(20), fechaentrega date not null); create view pedidosretrasados as select numpedido, nifproveedor, retraso from pedidos where sysdate>fechaentrega; create trigger GestionPedidos instead of delete on pedidosretrasados for each row begin update pedidosretrasados set retraso= SI ; update pedidos set retraso= SI ; where pedidos.nifproveedor in (select nifproveedor from pedidosretrasados); end; / BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 27
Triggers. Ejemplos (1).... insert into pedidos (codigo, precio, nifproveedor, fechaentrega) values (1, 25000, 482865R, 10-jan-2001 ); insert into pedidos (codigo, precio, nifproveedor, fechaentrega) values (2, 65000, 482865R, 10-jan-2003 ); insert into pedidos (codigo, precio, nifproveedor, fechaentrega) values (3, 50800, 482865R, 21-dec-2000 );... select * from pedidosretrasados; delete from pedidosretrasados; select * from pedidos; select * from pedidosretrasados; BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 28
Triggers. Ejemplos (2). create table categoria (id_categoria varchar(10)); create table empleado( nif varchar(9), nombre varchar(40), id_categoria varchar(10) not null); create table obra( id_obra varchar(40), localizacion varchar(40), jefe_obra varchar(9) not null, constraint obra_fk key (jefe_obra) references empleado(nif)); BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 29
Triggers. Ejemplos (2). REM Comprobar que el jefe que se asigna tiene la categoría adecuada create or replace trigger checkjefe before insert or update of jefe_obra on obra for each row declare cate varchar(9); begin select e.id_categoria into cate from empleado e where (e.nif= :new.jefe_obra); if cate!= Jefe Obra then raise_application_error(-204000, Categoria inadecuada ); end if; end; / BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 30
Triggers. Ejemplos (3). create table facturas_enviadas ( Numfact varchar(10), Fecha date, Total number(10), CIF varchar(9)); create table facturas_no_pagadas( Numfact varchar(10), Fecha date, Total number(10), CIF varchar(9)); create trigger facturas_impagadas after insert on facturas_enviadas for each row begin insert into facturas_no_pagadas values (:new.numfact, :new.fecha, :new_total, :new.cif); end; / BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 31
API JDBC El API JDBC permite el acceso externo a una base de datos, integrando las sentencias SQL dentro de un entorno de programación general, mediante el uso de bibliotecas de rutinas que interactúan con la base de datos. BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 32
API JDBC Se escribe un programa en Java. Cuando se necesita interacturar con la base de datos, utilizando una biblioteca de rutinas, se abre una conexión con la base de datos. Mediante JDBC se envía código SQL a la base de datos, se procesan los resultados que la base devuelve. Cuando se ha terminado se cierra la conexión. BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 33
API JDBC Establecer una conexión. Antes de acceder a la base de datos, se debe tener una conexión abierta entre el programa (cliente) y la base de datos (servidor). Esto supone dos pasos: 1. Cargar el driver del vendedor Class.forName( oracle.jdbc.driver.oracledriver ) 2. Hacer la conexión Connection con = DriverManager.getConnection ( jdbc:oracle:thin:@duero:1521:oratuti ) BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 34
API JDBC Sentencias JDBC Se ha de utilizar un objeto Sentencia JDBC para enviar sentencias SQL al SGBD. Se necesita tener una conexión activa para crear estos objetos: Statement stmt = con.createstatement (); Ahora, existe el objeto stmt, pero, de momento, no tiene sentencias para pasar al SGBD. BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 35
API JDBC Sentencias CREATE/INSERT/UPDATE El método executeupdate de la clase Statement permite crear una tabla, modificar y borrarla. También, permite modificar las tuplas que pertenecen a la tabla. Como todos estos comandos cambian el estado de la base de datos, el nombre del método contiene un Update. stmt.executeupdate ( CREATE TABLE... ); stmt.executeupdate ( INSERT INTO... ); BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 36
API JDBC Sentencias SELECT En este caso, el resultado de una consulta es un conjunto de tuplas (una tabla) y no se modifica el estado de la base de datos. El método a utilizar es executequery, que devuelve como resultado rs, un objeto de la clase ResultSet. ResultSet rs = stmt.executequery ( SELECT... ); BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 37
API JDBC Sentencias SELECT Debemos poder acceder a cada fila y a cada atributo de ellas. La clase ResultSet proporciona un cursor que nos permite acceder a cada fila de la tabla. Al principio, el cursor está justo antes de la primera fila. Cada invocación del método next produce un avance a la siguiente fila. Con los métodos getstring y getfloat podemos acceder a los valores de las columnas. BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 38
API JDBC Sentencias SELECT while ( rs.next () ) { variable1 = rs.getstring ( Atributo1 ); variable2 = rs.getfloat ( Atributo2 );... } BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 39
API JDBC Manejo de Errores El cliente (programa) que accede al servidor (Base de Datos) necesita conocer si ha ocurrido algún error en el acceso a los datos. JDBC permite este control con dos condiciones de error: SQLException: son excepciones Java que pueden provocar el fin de la ejecución. SQLWarning: son subclases de SQLException, que no representan errores fatales. BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 40
API JDBC Manejo de Errores En Java, las sentencias de las que esperamos recoger una excepción o un aviso se encierran dentro de un bloque try. Si una sentencia del bloque try lanza una excepción, se puede tratar en la sentencia catch correspondiente. try { stmt.executeupdate ( CREATE TABLE... );...} catch (SQLException ex) { System.err.println ( Excepción de SQL...);} BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 41
API JDBC Un ejemplo completo: import java.sql.*; class Bases2 { public static void main(string s[]) { Connection connection = null; try { String drivername = "oracle.jdbc.driver.oracledriver"; String driverurl = "jdbc:oracle:thin:@duero:1521:oratuti"; String username = "estad48"; String pwd = "pass48"; BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 42
API JDBC try {// Cargar el controlador JDBC Class.forName(driverName); } catch (ClassNotFoundException e) { System.out.println("No encuentro la clase " + drivername); } // Establecer una conexión con la Base de Datos. connection = DriverManager.getConnection(driverURL, username,pwd); // Crear un objeto que usaremos para mandar "statements" al DBMS Statement stmt = connection.createstatement(); // Tenemos la conexión preparada => podemos trabajar sobre la BD BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 43
API JDBC // Crear una tabla y poblarla // 1. Comprobamos si la tabla ya existe. Si fuese así, la eliminamos. tabla ResultSet mistablas = stmt. executequery("select table_name while (mistablas.next()){ from user_tables"); if (mistablas.getstring(1).equals("tablajdbc")){ ntes de crearla }//if }//while System.out.println("La tabla ya existe => BORRAR"); stmt.executeupdate("delete tablajdbc"); // vaciar la stmt.executeupdate("drop table tablajdbc");//eliminarla BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 44
API JDBC // 2. Creamos la tabla stmt.executeupdate("create TABLE tablajdbc(" + "local VARCHAR2(40), producto VARCHAR2(40), precio REAL)"); // 3. La poblamos stmt.executeupdate("insert INTO tablajdbc VALUES" + "('Local1', 'Cerveza', 3.06)"); // Ejecutar consultas ResultSet rs = stmt. executequery("select * from tablajdbc"); // Mostramos los resultados (la 2º columna) while (rs.next()) System.out.println("Producto = " + rs.getstring(2)); BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 45
API JDBC // Cerramos el resultado, la operación y la conexión mistablas.close(); rs.close(); stmt.close(); connection.close(); } catch (SQLException e) { // Recogemos cualquier otra posibilidad: fallo en la conexión, // petición o recepción de información e.printstacktrace(); } } //main }//Bases BD (I.T.Informática) M. Martínez, C. Hernández, C. Cuesta 46