La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Unidad 3.

Presentaciones similares


Presentación del tema: "Unidad 3."— Transcripción de la presentación:

1 Unidad 3

2 De acuerdo a lo visto, cómo es la organización o estructura de un programa en el servidor de BD?
Organización de programa en bloques.

3 CREATE… AS DECLARE… Sentencias SQL

4 Manejo de excepciones: control de errores.
PL/SQL usa bloque de exceptions. DECLARE .... excep EXCEPTION; /* (2) */ BEGIN ... IF ... THEN RAISE excep; /* (2) */ END IF; EXCEPTION WHEN TOO_MANY_ROWS THEN /* (1) */ sentencias_manejo_excepcion_sistema; WHEN excep THEN /* (2) */ sentencias_manejo_excepcion_usuario; WHEN OTHERS THEN ...; ; END;

5 SQL Server 2005 posee un mecanismo de manejo de excepciones en un formato de bloque TRY/CATCH:
BEGIN TRY INSERT INTO Sales.Currency (CurrencyCode, Name, ModifiedDate ) VALUES('LAE','Pol','01/06/2005') PRINT 'Inserción completada con exito.' END TRY BEGIN CATCH PRINT 'Inserción fallida.' END CATCH

6 BEGIN TRY int int, int = 100 = 0    -- Esta linea provoca un error de division por 0 = PRINT 'No hay error‘ END TRY BEGIN CATCH PRINT 'Se ha producido un error‘ END CATCH

7 SQL Server 2000 no maneja el TRY/CATCH.
Qué se ha usado para controlar errores? IF ELSE…PRINT…RETURN

8 @@ERROR. Variable global de sistema
Variable global de sistema. Almacena el número de error producido por la última sentencia Transact SQL ejecutada. Devuelve 0 si la última instrucción Transact-SQL se ejecutó con éxito. Si la instrucción causó un error, devuelve el número de error. El valor de cambia al finalizar cada instrucción Transact-SQL. Qué se aconseja? Guardar en una variable de tipo entero inmediatamente después de que se complete la instrucción Transact-SQL. El valor de la variable se puede usar posteriormente.

9 DECLARE @divisor int , @dividendo int , @resultado int
= 100 = 0 /*se genera una division por 0->error*/ = IF = 0 PRINT 'No hay error' ELSE PRINT 'Error de division'

10 DECLARE @divisor int , @dividendo int , @resultado int
= 100 = 0 /*se genera una division por 0->error*/ = /*esta linea vuelve a establecer a 0*/ PRINT 'Controlando el error ...' IF = 0 PRINT 'No hay error' ELSE PRINT 'Error de division'

11 DECLARE @divisor int,@dividendo int , @resultado int
declare @nu int = 100 = 0 = set print 'Controlando el error...' = 0 PRINT 'No hay error' ELSE PRINT 'Hay error: ' as varchar)

12 En ocasiones es necesario provocar voluntariamente un error;  nos puede interesar que se genere un error cuando los datos incumplen una regla de negocio. Se puede provocar un error en tiempo de ejecución a través de la función RAISERROR.

13 Raiserror. Devuelve un mensaje de error definido por el usuario y establece un indicador del sistema para registrar que se ha producido un error; más eficaz que PRINT para devolver mensajes a las aplicaciones. Sintaxis RAISERROR ( { msg_id | msg_str } { , severity , state }     [ , argument [ ,...n ] ] )     [ WITH option [ ,...n ] ]

14 msg_id. Número de mensaje de error definido por el usuario que está almacenado en la tabla sysmessages. Deben ser mayores de msg_str. Mensaje ad hoc con un formato similar al estilo de formato PRINT... Puede contener un máximo de 400 caracteres. Si el mensaje contiene más de 400 caracteres, solamente aparecerán los 397 primeros y se agregarán puntos suspensivos… Severity. Nivel de gravedad definido por el usuario que se asocia con este mensaje. Todos los usuarios pueden utilizar los niveles de gravedad de 0 a 18. State. Entero arbitrario entre 1 y 127 que representa información acerca del estado de llamada del error. Un valor negativo de state pasa a tener un valor predeterminado de 1. VER RESTO DE CONFIGURACION

15 Create procedure chequearpersona1 (@dni varchar(9))
as if exists (select * from persona where begin select nombre, apellido from persona where end else raiserror ('Valor pedido no existe', 16, 1) exec chequearpersona1 ' '

16 Es posible definir errores de usuario con el fin de poder reutilizarlos, y así ofrecer un comportamiento homogéneo. Esto puede realizarse a través del procedimiento almacenado del sistema sp_addmessage (especificando código de error, severidad, texto del error, e idioma). Pueden consultarse los errores existentes en sysmessages.

17 EXEC = = 16, @msgtext = 'No existe elemento buscado', @lang = 'us_english‘ SELECT * FROM master.dbo.sysmessages Create procedure chequearpersona1 varchar(9)) as if exists (select * from persona where begin select nombre, apellido from persona where end else raiserror (50001, 16, 1)

18 Apliquemos @@error y raiserror a algun procedimiento realizado anteriormente.
Que tipo de problema podria ser? Select? Qué error podría surgir con un select? Uso de

19 Create procedure chequearpersona (@dni varchar(9))
as if exists (select * from persona where begin select nombre, apellido from persona where end else print 'Persona no esta registrada'

20 Insertar un registro de persona.
Puede surgir un error ?

21 Create procedure insertarpersona5 char(1)) as insert into persona (DNI, Nombre, Apellido, Ciudad, DireccionCalle, DireccionNum, Telefono, FechaNacimiento, Varon) @Varon)

22 Hacer lo mismo con el siguiente PA (actualiza id de una titulacion)
create PROCEDURE updatetitulacion1 numeric(6)) AS if (select count(*) from titulacion where begin if (select count(*) from titulacion where update titulacion set where return 0 end else return 2 return 1

23 Uso de INTO en SELECT Into en select…

24 INTO (en SELECT). La cláusula INTO habilita para especificar que el conjunto de resultados se utilizará para crear una tabla nueva con el nombre definido en la cláusula: Crea una nueva tabla e inserta en ella las filas resultantes… Se suele utilizar para crear tablas de trabajo, o tablas intermedias; se crean para una determinada tarea y luego se borran. Se puede utilizar para crear una copia de seguridad de la tabla. Sintaxis. INTO new_table

25 SELECT * INTO new_table_name FROM old_tablename SELECT column_name(s) En BD Universidad: select * into copia from persona

26 select Nombre, Apellido
into copia1 from persona Where ciudad=‘Concepcion’ select Asignatura.Nombre as asig, persona.nombre, persona.apellido into copia2 from asignatura, profesor, persona Where asignatura.idprofesor=profesor.idprofesor and profesor.dni=persona.dni

27 No confundir con… INSERT INTO…SELECT: Inserción multiple de filas. La sentencia INSERT permite tambien insertar varios registros en una tabla. Pare ello se utiliza una combinación de la sentencia INSERT junto a una sentencia SELECT. El resultado es que se insertan todos los registros devueltos por la consulta.

28 Sintaxis. INSERT INTO <nombre_tabla> [(<campo1>[,<campo2>,...])] SELECT [(<campo1>[,<campo2>,...])] FROM <nombre_tabla_origen>; Se deben cumplir las siguientes normas: La lista de campos de las sentencias insert y select deben coincidir en número y tipo de datos. Ninguna de las filas devueltas por la consulta debe infringir las reglas de integridad de la tabla en la que vayamos a realizar la inserción.

29 create table ciudades (id int identity (1,1) primary key, ciudad varchar (30)) insert into ciudades (ciudad) select distinct ciudad from persona

30 Hacer un PA para la tabla persona, con parametro de entrada (ciudad) que realice un select de todas las personas de esas ciudad, y genere una copia de seguridad con esos datos.

31 Modificar PA usando @@error o @rowcount, raiserror

32 Cursor. Variable que permite recorrer un conjunto de resultados obtenidos a través de una SELECT fila a fila: permiten situarse en filas específicas del conjunto de resultados. Recuperan una fila o bloque de filas. Aceptan modificaciones de los datos de las filas en la posición actual del conjunto de resultados En qué se podrían relacionar los SELECT INTO e INSERT INTO SELECT con cursores?

33 Para trabajar con cursores se deben seguir los siguientes pasos:
Declarar el cursor, utilizando DECLARE Abrir el cursor, utilizando OPEN Leer los datos del cursor, utilizando FETCH ... INTO Cerrar el cursor, utilizando CLOSE Liberar el cursor, utilizando DEALLOCATE

34 Sintaxis General -- Declaración del cursor
DECLARE <nombre_cursor> CURSOR FOR <sentencia_sql> -- apertura del cursor OPEN <nombre_cursor> -- Lectura de la primera fila del cursor FETCH <nombre_cursor> INTO <lista_variables> WHILE = 0) BEGIN -- Lectura de la siguiente fila de un cursor ... END -- Fin del bucle WHILE -- Cierra el cursor CLOSE <nombre_cursor> -- Libera los recursos del cursor DEALLOCATE <nombre_cursor>

35 @@FETCH_STATUS. Variable global
Variable global. Devuelve el estado de la última instrucción FETCH de cursor ejecutada.

36 Ejemplo. Abrir un cursor y recorrerlo:
DECLARE persona_Cursor CURSOR FOR SELECT Nombre, Apellido, Ciudad FROM persona WHERE varon=1 OPEN persona_Cursor FETCH NEXT FROM persona_Cursor WHILE = 0 BEGIN END CLOSE persona_Cursor DEALLOCATE persona_Cursor

37 Ejemplo. Abrir un cursor, recorrerlo e imprimir:
varchar(20) varchar(20) varchar(20) DECLARE persona_Cursor CURSOR FOR SELECT Nombre, Apellido, Ciudad FROM persona WHERE varon=1 ORDER BY Apellido, Nombre OPEN persona_Cursor FETCH NEXT FROM @ciudad WHILE = 0 BEGIN PRINT +' +' vive en FETCH NEXT FROM persona_Cursor END CLOSE persona_Cursor DEALLOCATE persona_Cursor

38 Ejemplo. Abrir un cursor, recorrerlo y actualizar:
varchar(20) float float DECLARE asig_Cursor CURSOR FOR SELECT Nombre, creditos, costebasico FROM asignatura OPEN asig_Cursor FETCH NEXT FROM @coste WHILE = 0 BEGIN update asignatura set where END CLOSE asig_Cursor DEALLOCATE asig_Cursor

39 Ejecutar el siguiente cursor
Que hace?

40 SET NOCOUNT ON DECLARE @nom varchar(20), @cont varchar(30), @message varchar (80), @nombp varchar (20) PRINT ' proveedores almacen kollao ' DECLARE proov_cursor CURSOR FOR SELECT nombre, nombre_contacto FROM proveedor OPEN proov_cursor FETCH NEXT FROM proov_cursor @cont WHILE = 0 BEGIN PRINT ' ' = '----- productos por proveedor: ' + ' ,' DECLARE prod_cursor CURSOR FOR SELECT nombre_fantasia FROM proveedor, producto WHERE producto.proveedor=proveedor.codigo_proveedor and OPEN prod_cursor FETCH NEXT FROM prod_cursor IF <> 0 PRINT ' <<No productos>>' = ' ' END CLOSE prod_cursor DEALLOCATE prod_cursor CLOSE proov_cursor DEALLOCATE proov_cursor

41 /. Este cursor deja las contraseñas iguales al nombre de usuario
/* Este cursor deja las contraseñas iguales al nombre de usuario. La tabla Cliente tiene estos tres campos: CliCod, CliUser, CliPass */ -- declaramos las variables as int as varchar(50) as varchar(50) -- declaramos un cursor llamado "CURSORITO". declare CURSORITO cursor for select CliCod, CliUser, CliPass from Cliente open CURSORITO -- Avanzamos un registro y cargamos en las variables los valores encontrados en el primer registro fetch next from @pass     while = 0         begin         update Cliente set where         -- Avanzamos otro registro         fetch next from @pass         end -- cerramos el cursor close CURSORITO deallocate CURSORITO

42 Generar un PA que a traves de un cursor, imprima el nombre, creditos y cuatrimestre de las asignaturas registradas.

43 Generar un PA que a traves de un cursor, imprima el nombre, creditos y cuatrimestre de ciertas asignaturas registradas, de acuerdo a parametro de entrada (cuatrimestre).

44 Cursores con parametros.
Al declarar un cursor podemos definir: DECLARE <nombre_cursor> CURSOR [ LOCAL | GLOBAL ] [ FORWARD_ONLY | SCROLL ] [ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ] [ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ] [ TYPE_WARNING ] FOR <sentencia_sql> INVESTIGAR [ LOCAL | GLOBAL ] [ FORWARD_ONLY | SCROLL ] [ STATIC | DYNAMIC | FAST_FORWARD ] [ READ_ONLY]

45 Triggers-Disparadores

46 Clase especial de procedimiento almacenado que se ejecuta automáticamente (se “dispara”) cuando se produce un evento en el servidor de bases de datos. Se ejecuta siempre que se intenta modificar los datos de una tabla que el trigger protege: realizar un INSERT, UPDATE o DELETE…dependiendo de la accion especificada. No es posible evitar su ejecución. Los triggers se definen para una tabla específica, denominada tabla del trigger.

47 No es posible invocar directamente los triggers, que tampoco pasan ni aceptan parámetros.
Gran herramienta para controlar reglas de negocio más complejas que una simple integridad referencial. Ojo: el usuario no espera que el trigger le devuelva registros luego de agregar o modificar información.

48 Sintaxis. CREATE trigger <Nombre del trigger> ON <Nombre de la Tabla> FOR <INSERT l UPDATE l DELETE> AS Sentencias….

49 Un trigger para inserción de registros genera automáticamente una tabla en el cache con la información que intenta añadir, esta tabla se denomina INSERTED y es a través de esta tabla que se pueden hacer comparaciones en otras tablas. Un trigger para eliminación de registros genera automáticamente una tabla en el cache con la información que intenta eliminar, esta tabla se denomina DELETED y es a través de esta tabla que se pueden hacer comparaciones en otras tablas. Si se trata de un trigger para actualización se generan ambas tablas INSERTED con los nuevos datos y DELETED con la información que será reemplazada.

50 Un trigger se "dispara" sólo cuando la instrucción de modificación de datos finaliza.
SQL Server verifica la posible violación de tipos de datos, reglas o restricciones de integridad. El trigger y la instrucción que lo "dispara" se consideran una sola transacción que puede revertirse desde dentro del disparador. Si se detecta un error grave, se revierte toda la transacción.

51 create TRIGGER reminder ON persona
FOR INSERT, UPDATE AS PRINT 'Se está intentando modificar datos‘ /*RAISERROR...*/

52 INSERT Aplicar reglas de negocio…???

53 Las personas que se registren en almacenes Kollao como clientes deben ser mayores de 18 años.
Como seria un trigger que verifique esto?

54 create trigger insertclienteedad on cliente
for insert as datetime fecha_nacimiento from inserted if getdate()))<18 begin raiserror (‘No se aceptan clientes menores de 18 años',16,1) end else print ‘Se inserto cliente exitosamente'

55 create trigger insertclienteedad on cliente
for insert as datetime fecha_nacimiento from inserted if getdate()))<18 begin raiserror (‘No se aceptan clientes menores de 18 años',16,1) rollback transaction /*deshace la transaccion*/ end else print ' Se inserto cliente exitosamente '

56 Se necesita insertar un producto cuya fecha de vencimiento sea minimo en 15 dias despues del registro.

57 No se aceptan productos con un stock menor a 10.

58 No mas de 5 productos de un proveedor.

59 Insercion en compra. Cantidad comprada con tarjeta de credito no pueden ser de mayor de 10.

60 create trigger insertcompratc on compra
for insert as if (select forma_pago from inserted)='t' and (select cantidad from inserted)>10 begin raiserror ('No se aceptan compras con tarjeta de credito de cantidad mayor de 10 ',16,1) rollback transaction end else print 'Compra valida'

61 No se puede comprar una cantidad de producto mayor al stock.

62 Sin embargo, ese trigger no actualiza el stock, si es que éste es suficiente…

63 Veamos que pasa con Update.

64 Al modificar algun dato de sucursal, se debe manejar un respaldo de sus datos, incluida fecha y usuario que genero la modificacion.

65 create table auditsuc (nr int identity (1,1) primary key, cod varchar(6), dir varchar (50), tel varchar (12), fecha datetime, usuario varchar(10))

66 create trigger modsucursal on sucursal
for update as varchar varchar(12) codigo_sucursal from deleted) direccion from deleted) telefono_sucursal from deleted) insert into auditsuc (cod, dir, tel,fecha,usuario) getdate(), user)

67 @@rowcount. Variable global
Variable global. Guarda el numero de filas afectadas por la ultima instrucción.

68 alter trigger modsucursal on sucursal
for update as if begin varchar varchar(12) codigo_sucursal from deleted) direccion from deleted) telefono_sucursal from deleted) insert into auditsuc (cod, dir, tel,fecha,usuario) getdate(), user) end else raiserror(‘No se pueden realizar actualizaciones de varias filas',16,1) rollback transaction

69 On UPDATE en una fila especifica…

70 create table auditsuc1 (nr int identity (1,1) primary key, cod varchar(6), tel varchar (12), fecha datetime, usuario varchar(10)) create trigger modsucursaltel on sucursal for update as if update(telefono_sucursal) begin varchar(12) codigo_sucursal from deleted) telefono_sucursal from deleted) insert into auditsuc1 (cod, tel,fecha,usuario) @tel, getdate(), user) end

71 No esta permitido realizar modificaciones los fines de semana

72 DELETE. Al eliminarse un proveedor, se debe manejar un respaldo de los datos eliminados.

73 create table auditproveedor
(nr int identity (1,1) primary key, cod varchar(6), nom varchar (20), contacto varchar (30), tel varchar (12), fecha datetime, usuario varchar(10))

74 create trigger delproveedor on proveedor
for delete as varchar varchar varchar(12) codigo_proveedor from deleted) nombre from deleted) nombre_contacto from deleted) telefono_contacto from deleted) insert into auditproveedor (cod, nom, contacto, tel ,fecha,usuario) @tel, getdate(), user)

75 create trigger delproveedor on proveedor
for delete as varchar varchar varchar(12) If begin codigo_proveedor from deleted) nombre from deleted) nombre_contacto from deleted) telefono_contacto from deleted) insert into auditproveedor (cod, nom, contacto, tel ,fecha,usuario) @tel, getdate(), user) end Else Raiserror (‘No se puede eliminar mas de un proveedor a la vez’,16,1)

76 No se puede borrar mas de un proveedor a la vez!!!

77 create trigger delproveedor1 on proveedor
for delete as IF (SELECT COUNT(*) FROM Deleted) > 1 BEGIN RAISERROR(‘No puede borrar más de un proveedor al mismo tiempo.’,16, 1) ROLLBACK TRANSACTION END

78 create trigger delproveedor1 on proveedor
for delete as IF > 1 BEGIN RAISERROR(‘No puede borrar más de un proveedor al mismo tiempo.’,16, 1) ROLLBACK TRANSACTION END

79 Conocer triggers creados:
select * from sysobjects where type = ‘TR’ Obtener el texto del trigger sp_helptext nombretrigger

80 ALTER TRIGGER DROP Trigger Deshabilitar ALTER TABLE compra DISABLE TRIGGER insertcomprastock Habilitar ENABLE TRIGGER insertcomprastock

81 **************


Descargar ppt "Unidad 3."

Presentaciones similares


Anuncios Google