Módulo VI: Procedimientos y Desencadenadores Procedimientos Almacenados Implementación de Desencadenadores © Maximiliano Odstrcil - 1 Procedimientos Almacenados Introducción Creación, Ejecución y Modificación Uso de Parámetros Procedimientos Extendidos Manejo de Mensajes de Error © Maximiliano Odstrcil - 2 Introducción Definición Ventajas de los SP Proceso Inicial de los SP Proceso Subsiguiente de los SP © Maximiliano Odstrcil - 3 Definición (1) Un Procedimiento Almacenado (Stored Procedure) es una colección de sentencias SQL, con un nombre, almacenadas en el servidor, dentro de la BD. La finalidad de un procedimiento almacenado es análoga a la de una función, subprograma o método en un lenguaje de programación: encapsular tareas repetitivas. © Maximiliano Odstrcil - 4 Definición (2) Características: Soportan la declaración de variables, ejecución condicional y otras características de programación. Aceptan parámetros de entrada y devuelven valores. Devuelven un valor de estado que indica éxito o falla. Pueden llamar a otros procedimientos almacenados. © Maximiliano Odstrcil - 5 Definición (3) Tipos de procedimientos: Del sistema Locales Temporales Remotos Extendidos © Maximiliano Odstrcil - 6 Definición (4) Procedimientos almacenados del sistema: Procedimientos almacenados con que cuenta el SGBDR. Sirven para devolver la información de las tablas del sistema y ejecutar tareas de mantenimiento. MySQL no tiene estos tipos de procedimientos. En SQL Server se almacenan en la BD master y sus nombres comienzan con sp_. Ejemplo: sp_help. © Maximiliano Odstrcil - 7 Definición (5) Procedimientos almacenados locales: Procedimientos creados en las BD de usuario individuales. Procedimientos almacenados temporales: En SQL Server sus nombres empiezan con # o ## (si son locales o globales). No son soportados por MySQL. Procedimientos almacenados remotos: Soportan la funcionalidad de consultas distribuidas. © Maximiliano Odstrcil - 8 y operaciones Definición (6) Procedimientos almacenados extendidos: Procedimientos implementados como vínculos dinámicos a librerías (DLLs) que se ejecutan fuera del ambiente del servidor. No son soportados por MySQL. En SQL Server, sus nombres comienzan con xp_ y son ejecutados de manera similar a los SP. Algunos procedimientos almacenados de sistema llaman en su cuerpo a estos procedimientos. © Maximiliano Odstrcil - 9 Ventajas de los SP (1) Encapsulan la lógica de negocio y crean una lógica de la aplicación reusable: Las reglas o políticas de negocio encapsuladas en SP se pueden modificar en un único lugar. Todos los clientes pueden usar los mismos procedimientos almacenados asegurándose un acceso consistente a los datos. Ocultan a los usuarios la complejidad subyacente y detalles internos de la BD: Si todas las funciones de negocio se soportan mediante un conjunto de procedimientos almacenados, los usuarios no deben acceder a las tablas directamente. © Maximiliano Odstrcil - 10 Ventajas de los SP (2) Proveen mecanismos de seguridad: Se puede asignar permisos a los usuarios para ejecutar un procedimiento almacenado, aún cuando no tengan permisos para acceder a las tablas o vistas a que hacen referencia los procedimientos. Mejoran la perfomance: Los procedimientos almacenados implementan varias tareas mediante una serie de sentencias SQL. Se puede aplicar lógica condicional a los resultados de las primeras sentencias para determinar las siguientes. Todas estas sentencias forman parte de un único plan de ejecución. © Maximiliano Odstrcil - 11 Ventajas de los SP (3) Reducen el tráfico en la red: En vez de mandar miles de sentencias SQL por la red, los usuarios mandan una única sentencia (el llamado al SP al servidor) y reciben la respuesta. Reducen la vulnerabilidad debido a los ataques de SQL injection: Mediante el uso de parámetros en el código SQL se reduce la posibilidad que se puedan embeber sentencias SQL en los valores de los parámetros. © Maximiliano Odstrcil - 12 Proceso Inicial de los SP (1) Plan de ejecución: muestra cómo navega por las tablas y vistas el SGBDR, y cómo utiliza los índices para ejecutar una consulta. Se puede ver el plan de ejecución de la consulta que se ejecutó (plan real), o la forma en que el SGBDR ejecutará la consulta (plan estimado). Estos planes pueden diferir ligeramente ya que el SGBDR tiene en cuenta otras operaciones que se estén ejecutando en el plan real. © Maximiliano Odstrcil - 13 Proceso Inicial de los SP (2) El proceso de creación de un SP consiste de 4 etapas: Análisis sintáctico (parsing): el SGBDR controla la sintaxis del cuerpo del procedimiento y lo prepara para su optimización. En esta etapa no se controlan los nombres de los objetos o columnas. Normalización: el SGBDR verifica que todos los nombres de objetos y columnas referenciados en el cuerpo del procedimiento sean correctos y válidos. © Maximiliano Odstrcil - 14 Proceso Inicial de los SP (3) El proceso de creación de un SP consiste de 4 etapas: Compilación: el SGBDR construye el plan de ejecución para el SP, creando grafos para todas las sentencias del tipo DML, los cuales son usados por el optimizador para optimizar el plan de ejecución, el cual se guarda en el cache de procedimientos. © Maximiliano Odstrcil - 15 Proceso Inicial de los SP (4) El proceso de creación de un SP consiste de 4 etapas: Optimización: el optimizador determina el costo de los diferentes posibles planes de ejecución, eligiendo el menor. Para esto tiene en cuenta: Cantidad de datos en las tablas y naturaleza de sus índices. Los operadores involucrados en la cláusula WHERE. La presencia de Joins, UNION, GROUP BY y ORDER BY. © Maximiliano Odstrcil - 16 Proceso Inicial de los SP (5) La primera vez que se ejecuta un SP, el SGBDR arma un plan de ejecución (optimizado) para el mismo y lo guarda en el cache de procedimientos. El cache de procedimientos es un área de memoria que guarda temporalmente los planes de ejecución compilados. La permanencia de los planes de ejecución viene dada por: El tiempo requerido para su recompilación (costo). Su frecuencia de uso (edad). © Maximiliano Odstrcil - 17 Proceso Inicial de los SP (6) Un plan de ejecución consiste del plan en sí mismo y el contexto de ejecución: Execution context connection 1 Execution context connection 2 Execution context connection 3 Parameter value: 12 Parameter value: 24 Parameter value: 36 Query plan SELECT * FROM MyTable WHERE PriKey = ? © Maximiliano Odstrcil - 18 Procedure cache Age Cost Proceso Inicial de los SP (7) Creación Creación Parsing Parsing Ejecución Ejecución Optimización Optimización (primera (primeravez vez oorecompilación) recompilación) Compilación Compilación © Maximiliano Odstrcil - 19 Entradas Entradas en en las las tablas tablas sysobjects sysobjects yy syscomments syscomments Plan Plan de de compilación compilación en en el el cache cache de de proc. proc. Proceso Subsiguiente de los SP (1) Una vez que se ejecutó un SP, su plan de ejecución permanece en memoria, por lo que sucesivas ejecuciones, cada una con un contexto de ejecución diferente (incluyendo parámetros y variables), pueden compartirlo, evitando los pasos de análisis, compilación y optimización (ejecución más rápida). La reutilización de los planes de ejecución es una de las mayores ventajas de los SP. © Maximiliano Odstrcil - 20 Creación, Ejecución y Modificación Creación de SP Recomendaciones Ejecución de SP Modificación y Borrado de SP © Maximiliano Odstrcil - 21 Creación de SP (1) Se puede crear un SP de manera similar a la creación de vistas, con un asistente o mediante la sentencia CREATE PROCEDURE. Consideraciones: Los SP pueden referenciar tablas, vistas, SP y tablas temporales. Si un SP crea una tabla temporal local, ésta deja de existir cuando termina la ejecución del SP. En SQL Server la sentencia CREATE PROCEDURE es un batch por si mismo. La sentencia CREATE PROCEDURE puede incluir casi cualquier sentencia SQL. © Maximiliano Odstrcil - 22 Creación de SP (2) Consideraciones: En SQL Server, para ejecutar CREATE PROCEDURE se debe ser miembro de los roles sysadmin o db_owner, o se debe tener permiso de creación de procedimientos. SQL Server: CREATE CREATE PROC PROC dbo.overdue_books dbo.overdue_books AS AS SELECT SELECT ** FROM FROM dbo.loan dbo.loan WHERE WHERE due_date due_date << GETDATE() GETDATE() GO GO © Maximiliano Odstrcil - 23 Creación de SP (3) MySQL: DELIMITER DELIMITER // // CREATE CREATE PROCEDURE PROCEDURE verEmpleados() verEmpleados() BEGIN BEGIN SELECT SELECT ** FROM FROM Employees; Employees; END END // // DELIMITER DELIMITER ;; © Maximiliano Odstrcil - 24 Creación de SP (4) Los SP pueden anidarse (cuando un SP llama a otro SP). La características son: Puede haber hasta 32 niveles de anidamiento (SQL Server). El nivel de anidamiento actual se almacena en la variable global llamada @@nestlevel (SQL Server). Si un SP llama a un segundo SP, este último puede acceder a todos los objetos definidos localmente en el primero. © Maximiliano Odstrcil - 25 Creación de SP (5) En SQL Server: Para ver información sobre los SP se pueden usar los procedimientos sp_help, sp_helptext y sp_depends. Para obtener una lista de SP: sp_stored_procedures. En MySQL: Para ver información sobre un SP se puede ejecutar la sentencia SHOW CREATE PROCEDURE nombre; Para obtener una lista de SP: SHOW PROCEDURE STATUS; © Maximiliano Odstrcil - 26 Recomendaciones En SQL Server, se debe tratar de evitar romper la cadena de permisos, por lo que se recomienda que el usuario dbo sea el dueño de los procedimientos (similar a las vistas). Realizar un procedimiento por cada tarea (cohesión). Crear, probar y corregir los procedimientos en el servidor, luego hacer la prueba en los clientes. En SQL Server, evitar el uso del prefijo sp_ para los procedimientos. Usar las mismas configuraciones de conexión para todos los SP. Minimizar el uso de procedimientos temporales. © Maximiliano Odstrcil - 27 Ejecución de SP (1) Los procedimientos almacenados se pueden ejecutar por sí mismos: SQL Server: se emplea la sentencia EXEC[UTE] seguida del nombre del SP y sus parámetros: EXEC EXEC overdue_books overdue_books MySQL: se emplea la sentencia CALL seguida del nombre del SP y sus parámetros: CALL CALL verEmpleados(); verEmpleados(); © Maximiliano Odstrcil - 28 Ejecución de SP (2) En SQL Server los SP también se pueden ejecutar como parte de una sentencia INSERT, la cual puede poblar una tabla con el resultado (ResultSet) devuelto por un SP (la tabla debe existir y los tipos de datos y columnas deben coincidir): INSERT INSERT INTO INTO customers customers EXEC EXEC employee_customer employee_customer © Maximiliano Odstrcil - 29 Modificación y Borrado de SP (1) Los SP son modificados en respuesta a los requisitos del usuario o a cambios en las tablas subyacentes. En SQL Server, para modificar un SP existente se puede usar un asistente o bien la sentencia ALTER PROC[EDURE]. En MySQL, la sentencia ALTER PROCEDURE sólo permite modificar algunas características de un SP, no su cuerpo ni parámetros. © Maximiliano Odstrcil - 30 Modificación y Borrado de SP (2) Consideraciones (SQL Server): Se deben incluir las opciones que correspondan para la modificación del procedimiento, como WITH ENCRYPTION, WITH RECOMPILE, etc. La sentencia sólo modifica un SP. Si el SP llama a otros, éstos no se ven afectados. Se necesita tener determinados permisos para modificar el SP. © Maximiliano Odstrcil - 31 Modificación y Borrado de SP (3) El siguiente ejemplo modifica el SP overdue_books: ALTER ALTER PROC PROC overdue_books overdue_books AS AS SELECT SELECT CONVERT(char(8),due_date,1) CONVERT(char(8),due_date,1) date_due, date_due, isbn, isbn, copy_no, copy_no, SUBSTRING(title, SUBSTRING(title, 1, 1, 30)title, 30)title, member_no, member_no, lastname lastname FROM FROM OverdueView OverdueView ORDER ORDER BY BY due_date due_date GO GO © Maximiliano Odstrcil - 32 Modificación y Borrado de SP (4) Para borrar un SP se puede usar un asistente o la sentencia DROP PROC[EDURE]. SQL Server: DROP DROP PROC PROC overdue_books overdue_books MySQL: DROP DROP PROCEDURE PROCEDURE verEmpleados; verEmpleados; © Maximiliano Odstrcil - 33 Uso de Parámetros Parámetros de Entrada Ejecución de SP con Parámetros Retorno de Valores de Salida Recompilación Explícita de SP © Maximiliano Odstrcil - 34 Parámetros de Entrada (1) Permiten pasar información a los SP. Se los debe declarar en la sentencia CREATE PROCEDURE. Consideraciones: Verificar al principio del SP los valores de entrada para atrapar posibles valores inválidos. Proveer valores por defecto apropiados (depende del SGBDR). El máximo número de parámetros depende del SGBDR. El máximo número de variables locales de un SP es limitado solamente por la memoria disponible (depende del SGBDR). Los parámetros tienen un ámbito local al SP. © Maximiliano Odstrcil - 35 Parámetros de Entrada (2) Sintaxis para SQL Server: @parámetro tipo_dato [ = valor_defecto] CREATE CREATE PROC PROC dbo.find_isbn dbo.find_isbn @title @title longstring longstring == null, null, @translation @translation char(8) char(8) == 'English' 'English' AS AS IF IF @title @title is is null null BEGIN BEGIN PRINT PRINT "Please "Please provide provide aa title title (or (or partial partial title) title) and and the the translation" translation" PRINT PRINT "find_isbn "find_isbn 'Oliver%', 'Oliver%', 'Japanese'" 'Japanese'" .. .. .. © Maximiliano Odstrcil - 36 Parámetros de Entrada (3) Sintaxis para MySQL: parámetro tipo_dato DELIMITER DELIMITER // // CREATE CREATE PROCEDURE PROCEDURE verUnEmpleado(ide verUnEmpleado(ide INTEGER) INTEGER) BEGIN BEGIN SELECT SELECT ** FROM FROM Employees Employees WHERE WHERE EmployeeID EmployeeID == ide; ide; END END // // DELIMITER DELIMITER ;; © Maximiliano Odstrcil - 37 Ejecución de SP con Parámetros (1) En SQL Server se puede llamar un SP con parámetros de 2 formas: Pasando los valores por referencia (forma explícita) Pasando los valores por posición © Maximiliano Odstrcil - 38 Ejecución de SP con Parámetros (2) Paso de valores por referencia: en la sentencia EXEC se especifica el parámetro de la forma @parámetro = valor. El orden de los parámetros puede ser cualquiera. Se pueden omitir parámetros, en cuyo caso adoptan el valor por defecto o el valor nulo. Se puede especificar @parámetro = DEFAULT. EXEC EXEC addadult addadult @firstname @firstname == 'Linda', 'Linda', @lastname @lastname == @street @city @street == 'Dogwood 'Dogwood Drive', Drive', @city @state @zip @state == 'CA', 'CA', @zip == '94203' '94203' © Maximiliano Odstrcil - 39 'LaBrie', 'LaBrie', == 'Sacramento', 'Sacramento', Ejecución de SP con Parámetros (3) Paso de valores por posición: Se pasan los valores en el mismo orden en que fue definido el SP. Se pueden omitir parámetros en valores por defecto, pero no se debe interrumpir la secuencia. Se usan también valores nulos y DEFAULT como parámetros. EXEC EXEC addadult addadult 'LaBrie', 'LaBrie', 'Linda', 'Linda', null, null, 'Dogwood 'Dogwood Drive', Drive', 'Sacramento', 'Sacramento', 'CA', 'CA', '94203', '94203', null null © Maximiliano Odstrcil - 40 Ejecución de SP con Parámetros (4) En MySQL sólo se pueden pasar los valores por posición: Se pasan los valores en el mismo orden en que fue definido el SP. Se usan también valores nulos como parámetros. CALL CALL verUnEmpleado('Sales verUnEmpleado('Sales Representative', Representative', 'Ms.'); 'Ms.'); © Maximiliano Odstrcil - 41 Retorno de Valores de Salida (1) Un SP puede devolver información al SP o cliente que lo llama en forma de parámetros de salida. En SQL Server, para indicar que un parámetro es de salida se emplea la cláusula OUTPUT en la definición del SP: CREATE CREATE PROCEDURE PROCEDURE dbo.mathtutor dbo.mathtutor @m1 @m1 smallint, smallint, @m2 @m2 smallint, smallint, @result @result smallint smallint OUTPUT OUTPUT AS AS SET SET @result @result == @m1 @m1 ** @m2 @m2 GO GO © Maximiliano Odstrcil - 42 Retorno de Valores de Salida (2) En MySQL, los parámetros pueden ser de 3 tipos: IN: modo por defecto. Implica que quien llame al SP debe proporcionar ese parámetro. El SP trabaja con una copia de este parámetro. OUT: el valor de este parámetro se puede cambiar en el SP. El SP no puede acceder al valor inicial de este parámetro cuando empieza. INOUT: combinación de las 2 opciones anteriores. © Maximiliano Odstrcil - 43 Retorno de Valores de Salida (3) Ejemplo en MySQL: DELIMITER DELIMITER // // CREATE CREATE PROCEDURE PROCEDURE cantEmpleados(t cantEmpleados(t VARCHAR(30), VARCHAR(30), toc toc VARCHAR(25), VARCHAR(25), out out cant cant integer) integer) BEGIN BEGIN SELECT SELECT count(EmployeeID) count(EmployeeID) INTO INTO cant cant FROM FROM Employees Employees WHERE WHERE (Title (Title == t) t) AND AND (TitleOfCourtesy (TitleOfCourtesy == toc) toc) ;; END END // // DELIMITER DELIMITER ;; © Maximiliano Odstrcil - 44 Retorno de Valores de Salida (4) En SQL Server, para llamar a un SP con parámetros de salida también se emplea la cláusula OUTPUT. La sentencia que llama al SP debe tener una variable para guardar el valor de salida, que puede ser de cualquier tipo de datos, salvo text o image. DECLARE DECLARE @answer @answer smallint smallint EXECUTE EXECUTE mathtutor mathtutor 5, 5, 6, 6, @answer @answer OUTPUT OUTPUT SELECT SELECT 'The 'The result result is: is: '' ,, @answer @answer © Maximiliano Odstrcil - 45 Retorno de Valores de Salida (5) En MySQL, para llamar a un SP con parámetros de salida se hace: CALL CALL cantEmpleados('Sales cantEmpleados('Sales Representative', Representative', 'Ms.', 'Ms.', @cant); @cant); SELECT SELECT @cant; @cant; © Maximiliano Odstrcil - 46 Recompilación Explícita de SP (1) A veces SQL Server necesita reoptimizar los planes de ejecución de los SP: Se agregan nuevos índices Se cambian los datos en columnas indexadas Esta optimización se produce automáticamente cuando: Inicia SQL Server y se ejecuta la consulta por primera vez. Se cambian las tablas subyacentes. Si se agrega un índice, por ejemplo, se debe recompilar manualmente el SP. © Maximiliano Odstrcil - 47 Recompilación Explícita de SP (2) Un plan de ejecución consiste del plan en sí mismo y el contexto de ejecución, el cual incluye los valores de los parámetros. Si estos valores no son los mismos en las sucesivas llamadas al SP, la performance del SP puede disminuir, por lo que también resulta ventajoso recompilar un SP. © Maximiliano Odstrcil - 48 Recompilación Explícita de SP (3) Tres formas de recompilar explícitamente un SP: Especificar la opción WITH RECOMPILE en la sentencia CREATE PROCEDURE, con lo cual el SP no se guarda en el cache y se recompila cada vez que se ejecuta. Especificar la opción WITH RECOMPILE en la sentencia EXECUTE, con lo cual se crea un nuevo plan durante la ejecución del SP y se guarda en el cache. Usar el SP de sistema sp_recompile, con lo cual el SP se recompila la próxima vez que se ejecute. Si se lo ejecuta con una tabla o vista, todos los SP asociados son recompilados. © Maximiliano Odstrcil - 49 Procedimientos Extendidos Los SP extendidos son funciones dentro de una DLL que incrementan la funcionalidad de SQL Server. Características: Se programan usando la API de Open Data Services. Pueden incluir características de C y C++ por ejemplo. Pueden contener múltiples funciones. Se pueden llamar desde un cliente SQL Server. Se pueden agregar solamente a la BD master. EXEC EXEC master..xp_cmdshell master..xp_cmdshell 'dir 'dir c:\mssql7' c:\mssql7' © Maximiliano Odstrcil - 50 Manejo de Mensajes de Error (1) Para aumentar la efectividad de los SP, se deben incluir mensajes de error que comuniquen el estado de la transacción al usuario. En SQL Server, para implementar los mensajes de error se cuenta con: Sentencia RETURN Procedimiento sp_addmessage Función @@error Sentencia RAISERROR © Maximiliano Odstrcil - 51 Manejo de Mensajes de Error (1) Sentencia RETURN: Sale de una consulta o SP incondicionalmente. Puede retornar un valor de estado entero llamado código de retorno. SQL Server devuelve automáticamente 0 de cualquier SP, a menos que se especifique otro valor. © Maximiliano Odstrcil - 52 Manejo de Mensajes de Error (2) Sentencia RETURN: CREATE CREATE PROC PROC AddDept AddDept @name @name varchar(50), varchar(50), @groupname @groupname varchar(50), varchar(50), @deptid @deptid smallint smallint OUTPUT OUTPUT AS AS IF IF ((@name ((@name == '') '') OR OR (@groupname (@groupname == '')) '')) RETURN RETURN -1 -1 INSERT INSERT INTO INTO Department Department (Name, (Name, GroupName) GroupName) VALUES (@name, @groupname) VALUES (@name, @groupname) SET SET @deptid @deptid == SCOPE_IDENTITY() SCOPE_IDENTITY() RETURN 0 RETURN 0 GO GO © Maximiliano Odstrcil - 53 Manejo de Mensajes de Error (3) Sentencia RETURN: DECLARE DECLARE @dept @dept int, int, @res @res int int EXEC EXEC @res @res == AddDept AddDept 'Refunds', 'Refunds', '', '', @dept @dept OUTPUT OUTPUT IF IF (@res (@res SELECT SELECT ELSE ELSE SELECT SELECT © Maximiliano Odstrcil - 54 == 0) 0) @dept @dept 'Error' 'Error' Manejo de Mensajes de Error (4) Procedimiento sp_addmessage: Crea mensajes de error definidos por el usuario. Todos los mensajes de error (de usuario y sistema) se almacenan en la tabla sysmessages. Se pueden escribir en el Visor de Sucesos de Windows. EXEC EXEC sp_addmessage sp_addmessage @msgnum @msgnum == 50011, 50011, @severity @severity == 10, 10, @msgtext @msgtext == ‘El ‘El registro registro no no puede puede ser ser borrado’, borrado’, @with_log @with_log == ‘TRUE’ ‘TRUE’ © Maximiliano Odstrcil - 55 Manejo de Mensajes de Error (5) Función del sistema @@error: Contiene el número de error de la sentencia Transact-SQL más reciente. Se borra y resetea con cada sentencia que se ejecuta. Retorna un 0 cuando la sentencia se ejecuta satisfactoriamente. Se usa @@error para detectar un número de error específico o para abandonar un SP condicionalmente. .. .. IF IF @error @error <> <> 00 BEGIN BEGIN ROLLBACK ROLLBACK TRAN TRAN RETURN RETURN END END COMMIT COMMIT TRAN TRAN © Maximiliano Odstrcil - 56 Manejo de Mensajes de Error (6) Sentencia RAISERROR: Genera un mensaje de error definido por el usuario y avisa al sistema que ha ocurrido un error. Permite a la aplicación poner un mensaje de error definido por el usuario o bien una cadena construida dinámicamente. Puede escribir mensajes de error en el registro de errores de SQL o en el Visor de Sucesos de Windows. RAISERROR RAISERROR (50011,10,1) (50011,10,1) WITH WITH LOG LOG © Maximiliano Odstrcil - 57 Manejo de Mensajes de Error (7) /* /* Mensajes Mensajes de de error error definidos definidos por por el el EXEC EXEC sp_addmessage sp_addmessage 50010, 50010, 10, 10, 'Member 'Member EXEC EXEC sp_addmessage sp_addmessage 50011, 50011, 10, 10, 'Member 'Member EXEC EXEC sp_addmessage sp_addmessage 50012, 50012, 10, 10, 'Member 'Member Juvenile Juvenile member.' member.' EXEC EXEC sp_addmessage sp_addmessage 50013, 50013, 10, 10, 'Member 'Member loan.‘ loan.‘ usuario. usuario. */ */ number number not not found.' found.' cannot cannot be be deleted.' deleted.' is is responsible responsible for for currently currently has has books books on on CREATE CREATE PROCEDURE PROCEDURE dbo.removemember dbo.removemember @member_no @member_no member_no member_no == NULL NULL AS AS IF IF @member_no @member_no is is null null BEGIN BEGIN PRINT PRINT 'You 'You must must supply supply aa member member number' number' RETURN RETURN END END /*Sigue*/ /*Sigue*/ © Maximiliano Odstrcil - 58 Manejo de Mensajes de Error (8) IF IF NOT NOT EXISTS EXISTS (SELECT (SELECT ** FROM FROM member member WHERE WHERE member_no member_no == @member_no) @member_no) BEGIN BEGIN RAISERROR RAISERROR (50010, (50010, 10, 10, 1) 1) --Member --Member not not found. found. RETURN RETURN END END IF IF EXISTS EXISTS (SELECT (SELECT member_no member_no FROM FROM juvenile juvenile WHERE WHERE @member_no @member_no == adult_member_no) adult_member_no) BEGIN BEGIN RAISERROR RAISERROR (50011, (50011, 10, 10, 1) 1) RAISERROR RAISERROR (50012, (50012, 10, 10, 1) 1) PRINT PRINT 'Remove 'Remove the the juvenile juvenile member(s) member(s) first' first' RETURN RETURN END END /*Sigue*/ /*Sigue*/ © Maximiliano Odstrcil - 59 Manejo de Mensajes de Error (9) IF IF EXISTS EXISTS (SELECT (SELECT member_no member_no FROM FROM loan loan WHERE WHERE member_no member_no == @member_no) @member_no) BEGIN BEGIN RAISERROR RAISERROR (50013, (50013, 10, 10, 1) 1) --Books --Books on on loan. loan. RAISERROR RAISERROR (50011, (50011, 10, 10, 1) 1) --Member --Member cannot cannot be be deleted. deleted. RETURN RETURN END END /*Sigue*/ /*Sigue*/ © Maximiliano Odstrcil - 60 Manejo de Mensajes de Error (10) BEGIN BEGIN TRANSACTION TRANSACTION IF IF EXISTS EXISTS (SELECT (SELECT member_no member_no FROM FROM reservation reservation WHERE WHERE member_no member_no == @member_no) @member_no) BEGIN BEGIN PRINT PRINT 'Deleting 'Deleting Loan Loan Reservation Reservation information' information' DELETE reservation DELETE reservation WHERE WHERE member_no member_no == @member_no @member_no END END IF IF EXISTS EXISTS (SELECT (SELECT member_no member_no FROM FROM juvenile juvenile WHERE member_no WHERE member_no == @member_no) @member_no) BEGIN BEGIN DELETE DELETE juvenile juvenile WHERE WHERE member_no member_no == @member_no @member_no END END ELSE ELSE IF IF EXISTS EXISTS (SELECT (SELECT member_no member_no FROM FROM adult adult WHERE WHERE member_no = @member_no) member_no = @member_no) BEGIN BEGIN DELETE DELETE adult adult WHERE member_no WHERE member_no == @member_no @member_no END END /*Sigue*/ /*Sigue*/ © Maximiliano Odstrcil - 61 Manejo de Mensajes de Error (11) GO GO DELETE DELETE member member WHERE WHERE member_no member_no == @member_no @member_no SELECT SELECT 'Member 'Member '' ++ CONVERT(char(6), CONVERT(char(6), @member_no) @member_no) ++ 'has 'has been been removed removed from from the the library library database.' database.' COMMIT COMMIT TRANSACTION TRANSACTION © Maximiliano Odstrcil - 62 Manejo de Mensajes de Error (12) En MySQL, para implementar los mensajes de error se cuenta con la sentencia LEAVE: DELIMITER DELIMITER // // CREATE CREATE PROCEDURE PROCEDURE borrarOrden(ido borrarOrden(ido integer) integer) SALIR:BEGIN SALIR:BEGIN DECLARE DECLARE mensaje mensaje VARCHAR(100); VARCHAR(100); IF IF (ido (ido is is null) null) THEN THEN SET SET mensaje mensaje == 'Debe 'Debe especificar especificar una una orden'; orden'; SELECT SELECT mensaje; mensaje; LEAVE LEAVE SALIR; SALIR; END END IF; IF; ... ... END END // // DELIMITER DELIMITER ;; © Maximiliano Odstrcil - 63 Implementación de Desencadenadores Introducción a Triggers Definición de Triggers Ejemplos de Triggers Consideraciones de Perfomance © Maximiliano Odstrcil - 64 Introducción a Triggers Qué es un Trigger Usos de Triggers Consideraciones de Uso © Maximiliano Odstrcil - 65 Qué es un Trigger (1) Un desencadenador (trigger) es un tipo especial de SP que se ejecuta automáticamente cuando se modifican los datos de la tabla sobre la que se lo creó (trigger DML): Cuando ocurre una inserción, modificación o borrado de datos en una tabla, y se definió un trigger para la misma y para esa acción, se ejecuta automáticamente, no pudiéndose detener. Hay otros triggers que se ejecutan cuando se emplean sentencias del tipo CREATE, ALTER y DROP (trigger DDL). © Maximiliano Odstrcil - 66 Qué es un Trigger (2) Un trigger, junto con la sentencia que lo dispara, son tratados como una sola transacción (no hace falta iniciar explícitamente la transacción). Esta transacción se puede volver atrás dentro del cuerpo del trigger. Cualquier sentencia SQL que sea admitida por un SP se puede incluir dentro de un trigger. © Maximiliano Odstrcil - 67 Usos de Triggers (1) Características: Se usan para mantener la integridad de datos. No devuelven valores de consulta. Su principal ventaja es que manejan complejidad de procesamiento. © Maximiliano Odstrcil - 68 Usos de Triggers (2) Usos: Cambios en cascada de tablas relacionadas: un trigger para borrado en la tabla “Compras” puede borrar todas las filas de la tabla “LineasCompras” (estos cambios se pueden ejecutar más eficientemente empleando integridad referencial en cascada). Forzar integridad de datos de manera compleja: los triggers pueden proteger contra inserciones, borrados y modificaciones incorrectas, e imponer restricciones más complejas que las definidas mediante constraints de tipo CHECK (pueden referenciar columnas en otras tablas). © Maximiliano Odstrcil - 69 Usos de Triggers (3) Usos: Definición de mensajes de error de usuario: los triggers pueden mostrar mensajes de error definidos por el usuario. Comparar los estados antes y después: los triggers pueden comparar el estado de una modificación de datos antes y después de dicha modificación y luego ejecutar determinadas acciones según esta diferencia. © Maximiliano Odstrcil - 70 Consideraciones de Uso (1) Los triggers son reactivos mientras que las constraints son proactivas. Los triggers se disparan después de la ejecución de sentencias INSERT, UPDATE o DELETE. Las constraints se verifican primero: Se verifican antes de la sentencia y del trigger. Si se violan las constraints, el trigger nunca se ejecuta. Las tablas pueden tener múltiples triggers del mismo tipo (INSERT, UPDATE o DELETE) sin orden de ejecución. © Maximiliano Odstrcil - 71 Consideraciones de Uso (2) Los dueños de tablas deben tener permisos para crear, modificar y borrar triggers. No se puede crear triggers en vistas ni en tablas temporales, pero sí las pueden referenciar. No deben retornar ResultSets: Aunque pueden hacerlo, no tiene sentido devolver filas ya que las aplicaciones no lo esperan. © Maximiliano Odstrcil - 72 Consideraciones de Uso (3) No admiten parámetros. En SQL Server se puede usar la función del sistema @@ROWCOUNT para determinar el número de filas afectadas en una transacción. © Maximiliano Odstrcil - 73 Definición de Triggers Creación de Triggers Triggers INSERT Triggers DELETE Triggers UPDATE Modificación y Borrado de Triggers © Maximiliano Odstrcil - 74 Creación de Triggers (1) Desde la versión 2005 de SQL Server hay 2 tipos de trigger DML: Triggers AFTER: se ejecutan después que se produce la acción que dispara el trigger. Estos triggers sólo se pueden definir en tablas, y se pueden definir varios en una misma tabla. Triggers INSTEAD OF: se ejecutan en lugar de la acción usual del trigger. Se pueden definir también en vistas (por tabla o vista sólo se puede definir uno. © Maximiliano Odstrcil - 75 Creación de Triggers (2) Teniendo en cuenta los 2 tipos de triggers DML en SQL Server, si una tabla tiene definidas constraints, triggers del tipo AFTER y del tipo INSTEAD OF: Las constraints se verifican después de la ejecución de los triggers INSTEAD OF, pero antes de la de los triggers AFTER. Si se violan las constraints, las acciones de los triggers INSTEAD OF se vuelven atrás y los triggers AFTER nunca se disparan. © Maximiliano Odstrcil - 76 Creación de Triggers (3) En MySQL, al momento de definir un trigger DML se puede especificar el momento en el que se disparará: AFTER: el trigger se dispara después que se modifique cada fila. BEFORE: el trigger se dispara antes que se modifique cada fila. © Maximiliano Odstrcil - 77 Creación de Triggers (4) Los triggers se pueden crear con un asistente o bien con la sentencia CREATE TRIGGER. En la sentencia se especifica: El nombre del trigger La tabla a la cual pertenece el trigger El o los eventos por los que se dispara el trigger El cuerpo del procedimiento © Maximiliano Odstrcil - 78 Creación de Triggers (5) En SQL Server se puede emplear la cláusula IF UPDATE (columna) para focalizar la acción a una determinada columna, y no a todas las columnas de una tabla. Para crear un trigger se requiere determinados permisos. En SQL Server: Se debe ser miembro de los roles db_owner o sysadmin. Es recomendable que el dbo sea dueño de los objetos subyacentes para no romper la cadena de permisos. © Maximiliano Odstrcil - 79 Creación de Triggers (6) Los triggers pueden aceptar cualquier sentencia SQL, salvo: Todas las sentencias CREATE Todas las sentencias DROP ALTER (TABLE, DATABASE, PROCEDURE, TRIGGER) GRANT, REVOKE y DENY UPDATE STATISTICS RECONFIGURE LOAD DATABASE y RESTORE DATABASE © Maximiliano Odstrcil - 80 VIEW y Triggers INSERT (1) Un trigger INSERT se ejecuta cuando se agregan filas a una tabla sobre la que está creado. Funcionamiento (SQL Server): Cuando se dispara un trigger INSERT (porque se agregaron filas a la tabla sobre la que está creado) también se agregan filas a una tabla llamada inserted. La tabla inserted es una tabla lógica que mantiene una copia de las filas que se agregaron (contiene el log de la actividad de inserción). La tabla inserted permite referenciar sus filas desde el trigger. © Maximiliano Odstrcil - 81 Triggers INSERT (2) Funcionamiento (SQL Server): Las filas de la tabla inserted siempre son un duplicado de una o más filas en la tabla del trigger. El trigger puede examinar la tabla inserted para determinar las acciones a ejecutar. La actividad (INSERT, UPDATE, DELETE) se registra pero queda ilegible y puede leerse solamente a través de la tabla inserted. © Maximiliano Odstrcil - 82 Triggers INSERT (3) Se realiza una inserción a una tabla con un trigger INSERT INSERT INSERT loan loan VALUES VALUES (603, 4, 11, (603, 4, 11, 123, 123, GETDATE(), GETDATE(), (GETDATE() (GETDATE() ++ 30)) 30)) loan loan isbn isbn copy_no copy_no title_no title_no mem_no mem_no outdate outdate 11 44 33 © Maximiliano Odstrcil - 83 11 22 11 duedate duedate 1001 1001 1001 1001 02/13/91 02/13/91 02/27/91 02/27/91 1004 1004 1002 1002 02/14/91 02/14/91 02/28/91 02/28/91 1002 1002 1003 1003 02/14/91 02/14/91 02/28/91 02/28/91 Triggers INSERT (4) Se realiza una inserción a una tabla con un trigger INSERT INSERT INSERT loan loan VALUES VALUES (603, (603, 4, 4, 11, 11, 123, 123, GETDATE(), GETDATE(), (GETDATE() (GETDATE() ++ 30)) 30)) loan loan isbn isbn copy_no copy_no title_no title_no mem_no mem_no outdate outdate 11 44 603 4343 33 © Maximiliano Odstrcil - 84 11 41212 2121 11 1001 1001 1004 11 1004 1002 1004 1002 1004 1002 1002 1001 1001 1002 1001 123 1001 1002 1003 1002 1003 1002 1003 1003 02/13/91 02/13/91 02/14/91 02/13/91 02/15/91 02/13/91 02/14/91 02/14/91 02/14/91 02/14/91 02/14/91 duedate duedate 02/27/91 02/27/91 02/28/91 02/27/91 03/17/91 02/27/91 02/28/91 02/28/91 02/28/91 02/28/91 02/28/91 Triggers INSERT (5) Se realiza una inserción a una tabla con un trigger INSERT INSERT INSERT loan loan VALUES VALUES (603, (603, 4, 4, 11, 11, 123, 123, GETDATE(), GETDATE(), (GETDATE() (GETDATE() ++ 30)) 30)) loan loan isbn isbn copy_no copy_no title_no title_no mem_no mem_no outdate outdate 11 44 603 4343 33 11 41212 2121 11 1001 1001 1004 11 1004 1002 1004 1002 1004 1002 1002 1001 1001 1002 1001 123 1002 1001 1003 1002 1003 1002 1003 1003 02/13/91 02/13/91 02/14/91 02/13/91 02/15/91 02/14/91 02/13/91 02/14/91 02/14/91 02/14/91 02/14/91 duedate duedate 02/27/91 02/27/91 02/28/91 02/27/91 03/17/91 02/28/91 02/27/91 02/28/91 02/28/91 02/28/91 02/28/91 Se registra la inserción en la tabla inserted inserted inserted 603 44 603 © Maximiliano Odstrcil - 85 11 11 123 123 02/15/91 02/15/91 03/17/91 03/17/91 Triggers INSERT (6) Se ejecutan las acciones del trigger USE USE library library CREATE CREATE TRIGGER TRIGGER loan_insert loan_insert ON ON loan loan FOR FOR INSERT INSERT AS AS UPDATE UPDATE cc SET SET on_loan on_loan == 'Y' 'Y' FROM copy c INNER FROM copy c INNER JOIN JOIN inserted inserted II ON ON c.isbn c.isbn == i.sbn i.sbn AND AND c.copy_no c.copy_no == i.copy_no i.copy_no GO GO copy copy isbn isbn copy_no copy_no title_no title_no on_loan on_loan 11 44 603 44 33 © Maximiliano Odstrcil - 86 11 411 22 11 1001 1001 1004 11 1004 1004 1004 1002 1002 YY YY NN NN Triggers INSERT (7) En el caso de MySQL, para crear un trigger INSERT: DELIMITER DELIMITER // // CREATE TRIGGER CREATE TRIGGER Telefonos_Insert Telefonos_Insert AFTER AFTER INSERT INSERT ON ON Telefonos Telefonos FOR FOR EACH EACH ROW ROW BEGIN BEGIN --- cuerpo cuerpo del del trigger trigger END// END// DELIMITER DELIMITER ;; Si se especifica la opción FOR EACH ROW, el trigger se ejecuta una vez para cada fila, y si no se especifica esta opción, el trigger se ejecuta una única vez sin importar el número de filas. © Maximiliano Odstrcil - 87 Triggers INSERT (8) Así como en el caso de SQL Server se tenía acceso dentro del cuerpo de trigger a una tabla llamada inserted, en MySQL se tiene acceso a una tabla llamada NEW: En una inserción, la tabla NEW tiene las filas a insertar. En una modificación, la tabla NEW tiene las filas con los valores modificados. La tabla NEW es insensible a mayúsculas. © Maximiliano Odstrcil - 88 Triggers DELETE (1) Un trigger DELETE se ejecuta cuando se borran filas de una tabla sobre la que está creado. Funcionamiento: Cuando se dispara un trigger DELETE, porque se borraron filas de la tabla sobre la que está creado, estas filas agregan a una tabla llamada deleted. La tabla deleted es una tabla lógica que guarda una copia de las filas que han sido borradas (las filas en la tabla original no existen). © Maximiliano Odstrcil - 89 Triggers DELETE (2) Funcionamiento: La tabla borrada y la tabla deleted no tienen filas en común. La tabla deleted está siempre en el cache (memoria). La tabla deleted permite referenciar sus filas desde el trigger. Este trigger no se ejecuta con TRUNCATE TABLE. © Maximiliano Odstrcil - 90 Triggers DELETE (3) Se borran filas de una tabla con un trigger DELETE loan loan isbn isbn copy_no copy_no title_no title_no mem_no mem_no outdate outdate DELETE DELETE loan loan WHERE isbn WHERE isbn == 44 AND AND copy_no copy_no == 11 11 44 44 33 11 11 22 11 1001 1001 1004 1004 1004 1004 1002 1002 1001 1001 1001 1001 1002 1002 1003 1003 02/13/91 02/13/91 02/13/91 02/13/91 02/14/91 02/14/91 02/14/91 02/14/91 loan loan isbn isbn copy_no copy_no title_no title_no mem_no mem_no outdate outdate 11 44 44 33 © Maximiliano Odstrcil - 91 11 11 22 11 1001 1001 1004 1004 1004 1004 1002 1002 1001 1001 1001 1001 1002 1002 1003 1003 02/13/91 02/13/91 02/13/91 02/13/91 02/14/91 02/14/91 02/14/91 02/14/91 duedate duedate 02/27/91 02/27/91 02/27/91 02/27/91 02/28/91 02/28/91 02/28/91 02/28/91 duedate duedate 02/27/91 02/27/91 02/27/91 02/27/91 02/28/91 02/28/91 02/28/91 02/28/91 Triggers DELETE (4) Se registra el borrado en la tabla deleted loan loan isbn isbn copy_no copy_no title_no title_no mem_no mem_no outdate outdate 11 44 33 deleted deleted 44 11 © Maximiliano Odstrcil - 92 11 22 11 duedate duedate 1001 1001 1001 1001 02/13/91 02/13/91 02/27/91 02/27/91 1004 1004 1002 1002 02/14/91 02/14/91 02/28/91 02/28/91 1002 1002 1003 1003 02/14/91 02/14/91 02/28/91 02/28/91 1004 1004 1001 1001 02/13/91 02/13/91 02/27/91 02/27/91 Triggers DELETE (5) Se ejecutan las acciones del trigger USE USE library library CREATE CREATE TRIGGER TRIGGER loan_delete loan_delete ON ON loan loan FOR FOR DELETE DELETE AS AS UPDATE UPDATE cc SET SET on_loan on_loan == 'N' 'N' FROM FROM copy copy cc INNER INNER JOIN JOIN deleted deleted dd ON ON c.isbn c.isbn == d.isbn d.isbn AND AND c.copy_no c.copy_no == d.copy.no d.copy.no GO GO copy copy isbn isbn copy_no copy_no title_no title_no on_loan on_loan 11 44 44 33 © Maximiliano Odstrcil - 93 11 11 22 11 1001 1001 1004 1004 1004 1004 1002 1002 YY YY N NN NN Triggers DELETE (6) En MySQL, dentro de un trigger DELETE se tiene acceso a una tabla llamada OLD: Tiene las filas antes que sean modificadas o borradas. La tabla OLD es insensible a mayúsculas. © Maximiliano Odstrcil - 94 Triggers UPDATE (1) Un trigger UPDATE se ejecuta cuando se modifican filas de una tabla sobre la que está creado. Funcionamiento: Cuando se dispara un trigger UPDATE, porque se modificaron filas de la tabla sobre la que está creado, las filas originales se mueven a la tabla deleted, y las filas modificadas se insertan a la tabla inserted. El trigger puede estas 2 tablas, además de la tabla donde se están haciendo las modificaciones. © Maximiliano Odstrcil - 95 Triggers UPDATE (2) Funcionamiento: En SQL Server se puede definir el trigger para que monitorice los cambios de una columna específica solamente, para esto se usa la sintaxis: IF UPDATE columna. © Maximiliano Odstrcil - 96 Triggers UPDATE (3) Se modifican filas de una tabla con un trigger UPDATE UPDATE UPDATE member member SET SET member_no member_no == 10021 10021 WHERE WHERE member_no member_no == 1234 1234 © Maximiliano Odstrcil - 97 member member member_no member_no lastname lastname firstname firstname middleinitial middleinitial photograph photograph 10020 10020 10021 1234 10021 10022 10022 10023 10023 Anderson Anderson Barr Barr Barr Barr Anderson Anderson Andrew Andrew AA Andrew Andrew RR Bill NULL Bill NULL Bill BB Bill ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ Triggers UPDATE (4) Se modifican filas de una tabla con un trigger UPDATE UPDATE UPDATE member member SET SET member_no member_no == 10021 10021 WHERE WHERE member_no member_no == 1234 1234 member member member_no member_no lastname lastname firstname firstname middleinitial middleinitial photograph photograph 10020 10020 10021 1234 10021 10022 10022 10023 10023 Anderson Anderson Barr Barr Barr Barr Anderson Anderson Andrew Andrew AA Andrew Andrew RR Bill NULL Bill NULL Bill BB Bill Se registra la modificación como 2 pasos © Maximiliano Odstrcil - 98 deleted deleted 1234 Barr 1234 Barr Andrew Andrew RR ~~~ ~~~ inserted inserted 10021 10021 Barr Barr Andrew Andrew RR ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ Triggers UPDATE (5) Se ejecutan las acciones del trigger USE USE library library GO GO CREATE CREATE TRIGGER TRIGGER member_update member_update ON ON member member FOR FOR UPDATE UPDATE AS AS IF IF UPDATE UPDATE (member_no) (member_no) BEGIN BEGIN RAISERROR RAISERROR ('Transaction ('Transaction cannot cannot be be processed.\ processed.\ ***** Member number cannot be modified.', ***** Member number cannot be modified.', 10, 10, 1) 1) ROLLBACK TRANSACTION ROLLBACK TRANSACTION ... ... member member member_no member_no lastname lastname firstname firstname middleinitial middleinitial photograph photograph 10020 10020 10021 1234 10021 10022 10022 10023 10023 © Maximiliano Odstrcil - 99 Anderson Anderson Barr Barr Barr Barr Anderson Anderson Andrew Andrew AA Andrew Andrew RR Bill NULL Bill NULL Bill BB Bill ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ Triggers UPDATE (6) En MySQL, dentro de un trigger UPDATE se tiene acceso a las tablas OLD y NEW. © Maximiliano Odstrcil - 100 Modificación y Borrado de Triggers (1) Al igual que un SP, se puede modificar o borrar un trigger. Modificación (SQL Server): Se puede usar un asistente o la sentencia ALTER TRIGGER. Al igual que en un SP, se tiene la resolución de nombres posterior, que permite referenciar objetos todavía inexistentes. ALTER ALTER TRIGGER TRIGGER loan_insert loan_insert ON ON loan loan FOR FOR INSERT INSERT AS AS UPDATE UPDATE copy copy SET SET on_loan on_loan == 'y' 'y' FROM FROM copy copy INNER INNER JOIN JOIN inserted inserted ON ON copy.isbn copy.isbn == inserted.isbn inserted.isbn AND copy.copy_no AND copy.copy_no == inserted.copy_no inserted.copy_no © Maximiliano Odstrcil - 101 Modificación y Borrado de Triggers (2) Borrado de triggers: Los triggers se pueden borrar empleando un asistente o bien la sentencia DROP TRIGGER nombre_trigger. Cuando la tabla se borra, todos sus triggers asociados se borran también. El permiso para borrar un trigger lo tiene el dueño de la tabla únicamente. DROP DROP TRIGGER TRIGGER loan_insert loan_insert © Maximiliano Odstrcil - 102 Otros Triggers Anidados Triggers Recursivos Consideraciones de Performance © Maximiliano Odstrcil - 103 Triggers anidados (1) Un trigger puede contener sentencias INSERT, UPDATE y DELETE que afecten a otras tablas y, por ende, disparen otros triggers. En el caso de SQL Server, se puede habilitar o deshabilitar la opción de anidamiento en los triggers mediante el SP sp_configure (por defecto está habilitada esta opción). © Maximiliano Odstrcil - 104 Triggers anidados (2) Consideraciones: Si la opción de anidamiento está habilitada, estos disparos sucesivos pueden ocurrir hasta en 32 niveles (cuando un trigger en una cadena de anidamiento supera este nivel, el mismo termina y deshace la transacción). Un trigger no se dispara 2 veces en un llamado (autollamada). Como el trigger es una sola transacción, cualquier error en cualquier nivel causa el retroceso de toda la transacción. Se puede ver el nivel de anidamiento con la función @@NESTLEVEL. © Maximiliano Odstrcil - 105 Triggers anidados (3) El anidamiento es una herramienta muy poderosa para mantener la integridad de datos, pero hay ocasiones en que es necesario desactivarlo: Porque requieren un diseño planeado y una complejidad apreciable. Porque las modificaciones de las tablas no siguen el orden esperado. Para desactivar el anidamiento: sp_configure ‘nested triggers’, 0 © Maximiliano Odstrcil - 106 Triggers anidados (4) loan_update loan_update loan loan isbn isbn copy_no copy_no title_no title_no mem_no mem_no outdate outdate 11 44 44 33 copy_update copy_update 11 11 22 11 1001 1001 1004 1004 1004 1004 1002 1002 1001 1001 1001 1001 1002 1002 1003 1003 02/13/91 02/13/91 02/13/91 02/13/91 02/14/91 02/14/91 02/14/91 02/14/91 duedate duedate 02/27/91 02/27/91 02/27/91 02/27/91 02/28/91 02/28/91 02/28/91 02/28/91 El trigger de loan_update se ejecuta copy copy isbn isbn copy_no copy_no title_no title_no on_loan on_loan Ejecuta sentencia UPDATE 11 44 44 33 11 11 22 11 1001 1001 1004 1004 1004 1004 1002 1002 YY YY NN NN en la tabla copy El trigger copy_update se ejecuta Item will be due on 5/22/98 © Maximiliano Odstrcil - 107 Se envía el menaje Triggers Recursivos (1) Un trigger puede tener sentencias UPDATE, INSERT o DELETE que afecten a la misma tabla o a otra tabla. La activación de recursividad hace que el trigger pueda activarse él mismo hasta una condición de parada. Hay 2 tipos de recursividad: Directa Indirecta © Maximiliano Odstrcil - 108 Triggers Recursivos (2) Recursividad directa: Cuando una modificación de la tabla T1 causa que el trigger Trig1 se dispare, modifique la tabla T1 y se dispare nuevamente. Recursividad indirecta: Cuando una modificación de la tabla T1 cause que se dispare el trigger Trig1, que modifica la tabla T2, se dispara el trigger Trig2 de T2 que modifica la tabla T1, disparando Trig1 nuevamente. Los triggers recursivos son muy complejos y difíciles de implementar, pero brindan soluciones excelentes para relaciones autoreferenciadas. © Maximiliano Odstrcil - 109 Triggers Recursivos (3) Consideraciones: La recursividad admite 32 niveles de llamadas, y por defecto está deshabilitada. Las tablas inserted y deleted contienen las filas que corresponden sólo a las sentencias del último trigger. Si la opción de anidamiento está deshabilitada, también lo está la opción de recursividad. Si la opción de anidamiento está habilitada, la recursividad indirecta se puede producir, aunque la opción de recursividad esté deshabilitada. © Maximiliano Odstrcil - 110 Triggers Recursivos (4) Para activar la recursividad: sp_dboption nombre_db, ‘recursive triggers’, TRUE También se puede hacer: ALTER DATABASE DB SET RECURSIVE_TRIGGERS ON © Maximiliano Odstrcil - 111 Información sobre Triggers En SQL Server: Para ver los triggers de una tabla: nombre_tabla. Para ver la definición del trigger: nombre_trigger. sp_depends sp_helptext En MySQL: Para ver información sobre los triggers: SELECT * FROM information_schema.triggers © Maximiliano Odstrcil - 112 Consideraciones de Perfomance Los triggers se ejecutan rápidamente porque las tablas inserted y deleted están en el cache. El tiempo de ejecución está determinado por: Número de tablas referenciadas. Número de filas afectadas. Las acciones contenidas en un trigger son parte implícita de la misma transacción. © Maximiliano Odstrcil - 113 Ejemplos de Triggers Forzado de la Integridad de Datos Forzado de las Reglas de Negocio Auditoría © Maximiliano Odstrcil - 114 Forzado de la Integridad de Datos CREATE CREATE TRIGGER TRIGGER reservation_delete reservation_delete ON loan FOR ON loan FOR INSERT INSERT AS AS IF IF (SELECT (SELECT r.member_no r.member_no FROM FROM reservation reservation rr JOIN JOIN inserted i ON r.member_no = i.member_no inserted i ON r.member_no = i.member_no AND AND r.isbn r.isbn == i.isbn i.isbn )) >> 00 BEGIN BEGIN DELETE DELETE rr FROM FROM reservation reservation rr INNER INNER JOIN JOIN inserted inserted ii ON ON r.member_no r.member_no == i.member_no i.member_no AND AND r.isbn r.isbn == i.isbn i.isbn END END loan loan reservation reservation isbn isbn copy_no copy_no mem_no mem_no 11 44 44 33 11 11 11 22 11 22 © Maximiliano Odstrcil - 115 11 77 44 33 11 isbn isbn mem_no mem_no log_date log_date remarks remarks Insertado Insertado Trigger Triggerborra borrafila fila 11 11 22 33 44 11 22 11 11 77 07/14/98 07/14/98 07/12/98 07/12/98 06/07/98 06/07/98 07/14/98 07/14/98 07/14/98 07/14/98 ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ Forzado de las Reglas de Negocio (1) Los miembros con préstamos adeudados no pueden ser borrados Sentencia DELETE ejecutada en la tabla member member member member_no member_no lastname lastname firstname firstname 11 2323 3434 44 © Maximiliano Odstrcil - 116 Anderson Anderson Barr Barr Anderson Barr Anderson Barr Anderson Anderson Andrew Andrew Bill Andrew Bill Andrew Bill Bill Bill Bill Forzado de las Reglas de Negocio (2) Los miembros con préstamos adeudados no pueden ser borrados Sentencia DELETE ejecutada en la tabla member member member member_no member_no lastname lastname firstname firstname 11 2323 3434 44 © Maximiliano Odstrcil - 117 Anderson Anderson Barr Barr Anderson Barr Anderson Barr Anderson Anderson Andrew Andrew Bill Andrew Bill Andrew Bill Bill Bill Bill Forzado de las Reglas de Negocio (3) Los miembros con préstamos adeudados no pueden ser borrados Sentencia DELETE ejecutada en la tabla member member member member_no member_no lastname lastname firstname firstname 11 33 44 © Maximiliano Odstrcil - 118 Anderson Anderson Barr Barr Anderson Anderson Andrew Andrew Bill Bill Bill Bill Forzado de las Reglas de Negocio (4) Los miembros con préstamos adeudados no pueden ser borrados IF IF (Select (Select Count Count (*) (*) FROM FROM loan loan INNER INNER JOIN JOIN deleted deleted ON ON loan.member_no loan.member_no == deleted.member_no) deleted.member_no) >> 00 ROLLBACK ROLLBACK TRANSACTION TRANSACTION El código del trigger controla la tabla loan member member member_no member_no lastname lastname firstname firstname 11 33 44 © Maximiliano Odstrcil - 119 Anderson Anderson Barr Barr Anderson Anderson Andrew Andrew Bill Bill Bill Bill loan loan isbn isbn copy_no copy_no title_no title_no mem_no mem_no 11 44 44 33 11 11 22 11 11 44 44 33 11 11 22 33 Forzado de las Reglas de Negocio (5) Los miembros con préstamos adeudados no pueden ser borrados IF IF (Select (Select Count Count (*) (*) FROM FROM loan loan INNER INNER JOIN JOIN deleted deleted ON ON loan.member_no loan.member_no == deleted.member_no) deleted.member_no) >> 00 ROLLBACK ROLLBACK TRANSACTION TRANSACTION El código del trigger controla la tabla loan member member member_no member_no lastname lastname firstname firstname 11 33 44 Anderson Anderson Barr Barr Anderson Anderson Andrew Andrew Bill Bill Bill Bill loan loan isbn isbn copy_no copy_no title_no title_no mem_no mem_no 11 44 44 33 11 11 22 11 11 44 44 33 11 11 22 33 'No 'No se se puede puede procesar procesar la la transacción' transacción' 'Este miembro tiene libros 'Este miembro tiene libros prestados' prestados' © Maximiliano Odstrcil - 120 Forzado de las Reglas de Negocio (6) Los miembros con préstamos adeudados no pueden ser borrados IF IF (Select (Select Count Count (*) (*) FROM FROM loan loan INNER INNER JOIN JOIN deleted deleted ON ON loan.member_no loan.member_no == deleted.member_no) deleted.member_no) >> 00 ROLLBACK ROLLBACK TRANSACTION TRANSACTION Transacción vuelta atrás El código del trigger controla la tabla loan member member member_no member_no lastname lastname firstname firstname 11 2323 3434 44 Anderson Anderson Barr Barr Anderson Barr Anderson Barr Anderson Anderson Andrew Andrew Bill Andrew Bill Andrew Bill Bill Bill Bill loan loan isbn isbn copy_no copy_no title_no title_no mem_no mem_no 11 44 44 33 11 11 22 11 11 44 44 33 11 11 22 33 'No 'No se se puede puede procesar procesar la la transacción' transacción' 'Este miembro tiene libros 'Este miembro tiene libros prestados' prestados' © Maximiliano Odstrcil - 121 Auditoría CREATE CREATE TABLE TABLE `AuditProductos` `AuditProductos` (( `ID` `ID` INT INT NOT NOT NULL NULL AUTO_INCREMENT, AUTO_INCREMENT, `Tipo` `Tipo` CHAR(1) CHAR(1) NOT NOT NULL, NULL, `Fecha` `Fecha` DATETIME DATETIME NOT NOT NULL, NULL, `Host` VARCHAR(45) NOT `Host` VARCHAR(45) NOT NULL, NULL, `Usuario` VARCHAR(45) NOT `Usuario` VARCHAR(45) NOT NULL, NULL, `IDProducto` INT NOT NULL, `IDProducto` INT NOT NULL, `Nombre` `Nombre` VARCHAR(60) VARCHAR(60) NOT NOT NULL, NULL, `Descripcion` `Descripcion` TEXT TEXT NOT NOT NULL, NULL, PRIMARY KEY (`ID`) PRIMARY KEY (`ID`) ); ); DELIMITER DELIMITER // // CREATE TRIGGER CREATE TRIGGER `Trig_Productos_Ins` `Trig_Productos_Ins` AFTER INSERT ON AFTER INSERT ON `Productos` `Productos` FOR FOR EACH EACH ROW ROW BEGIN BEGIN INSERT INSERT INTO INTO AuditProductos AuditProductos VALUES VALUES (DEFAULT, 'I', NOW(), (DEFAULT, 'I', NOW(), SUBSTRING_INDEX(USER(),'@',-1), SUBSTRING_INDEX(USER(),'@',-1), SUBSTRING_INDEX(USER(),'@', SUBSTRING_INDEX(USER(),'@', 1), 1), NEW.IDProducto, NEW.IDProducto, NEW.Nombre, NEW.Nombre, NEW.Descripcion); NEW.Descripcion); END // END // DELIMITER DELIMITER ;; © Maximiliano Odstrcil - 122
© Copyright 2024