Los desencadenadores DML se utilizan frecuentemente para imponer las reglas de negocios y la integridad de los datos. SQL Server proporciona integridad referencial declarativa (DRI) mediante las instrucciones ALTER TABLE y CREATE TABLE. Sin embargo, DRI no proporciona integridad referencial entre bases de datos. La integridad referencial se refiere a las reglas acerca de la relación entre la clave principal y la clave externa de las tablas. Para exigir la integridad referencial, utilice las restricciones de tipo PRIMARY KEY y FOREIGN KEY en ALTER TABLE y CREATE TABLE. Si existen restricciones en la tabla de desencadenadores, se comprueban después de la ejecución del desencadenador INSTEAD OF y antes de la de AFTER. Si se infringen las restricciones, se revierten las acciones del desencadenador INSTEAD OF y el desencadenador AFTER no se ejecuta.
El primer y último desencadenador AFTER que se ejecuta en una tabla se puede especificar mediante sp_settriggerorder. Sólo se puede especificar el primer y último desencadenador AFTER para cada una de las operaciones INSERT, UPDATE y DELETE de una tabla. Si hay otros desencadenadores AFTER en la misma tabla, se ejecutan aleatoriamente.
Si una instrucción ALTER TRIGGER modifica el primer o último desencadenador, se elimina el primer o último atributo establecido en el desencadenador modificado, y el valor del orden se debe restablecer mediante sp_settriggerorder.
Un desencadenador AFTER se ejecuta sólo después de ejecutar correctamente la instrucción SQL desencadenadora. La ejecución correcta incluye todas las acciones referenciales en cascada y las comprobaciones de restricciones asociadas con el objeto actualizado o eliminado.
Si un desencadenador INSTEAD OF definido en una tabla ejecuta una instrucción en la tabla que normalmente volvería a activarlo, al desencadenador no se lo llama de forma recursiva. En su lugar, la instrucción se procesa como si la tabla no tuviera un desencadenador INSTEAD OF e inicia la cadena de operaciones de restricción y ejecuciones de desencadenadores AFTER. Por ejemplo, si para una tabla se define un desencadenador como INSTEAD OF INSERT, y éste ejecuta una instrucción INSERT en la misma tabla, la instrucción INSERT ejecutada por el desencadenador INSTEAD OF no vuelve a llamar al desencadenador. La instrucción INSERT ejecutada por el desencadenador inicia el proceso que realiza las acciones de restricción y activa cualquier desencadenador AFTER INSERT definido para la tabla.
Si un desencadenador INSTEAD OF definido en una vista ejecuta una instrucción en la vista que normalmente volvería a activarlo, no se llamará el desencadenador de forma recursiva. En su lugar, la instrucción se resuelve a modo de modificaciones en las tablas base subyacentes de la vista. En este caso, la definición de la vista debe cumplir todas las restricciones para una vista actualizable. Para obtener una definición de vistas actualizables, vea Modificar datos mediante una vista.
Por ejemplo, si para una tabla se define un desencadenador como INSTEAD OF UPDATE y éste ejecuta una instrucción UPDATE que hace referencia a la misma vista, la instrucción UPDATE, que ejecuta el desencadenador INSTEAD OF, no vuelve a llamar al desencadenador. La instrucción UPDATE que ejecuta el desencadenador se procesa en la vista, como si ésta no tuviera un desencadenador INSTEAD OF. Las columnas que modifica la instrucción UPDATE deben resolverse en una única tabla base. Cada vez que se modifica una tabla base subyacente se inicia la cadena para aplicar restricciones y activar los desencadenadores AFTER definidos para la tabla.
Probar las acciones de UPDATE o INSERT en columnas específicas
Se puede diseñar un desencadenador Transact-SQL que realice determinadas acciones según modificaciones de UPDATE o INSERT en columnas específicas. Para ello, utilice UPDATE() o COLUMNS_UPDATED en el cuerpo del desencadenador. UPDATE() comprueba los intentos de UPDATE o INSERT en una columna. COLUMNS_UPDATED comprueba las acciones de UPDATE o INSERT que se realizaron en varias columnas y devuelve un patrón de bits que indica las columnas que fueron insertadas o actualizadas.
Limitaciones de los desencadenadores
CREATE TRIGGER debe ser la primera instrucción en el proceso por lotes y sólo se puede aplicar a una tabla.
Un desencadenador se crea solamente en la base de datos actual; sin embargo, un desencadenador puede hacer referencia a objetos que están fuera de la base de datos actual.
Si se especifica el nombre del esquema del desencadenador (para calificar el desencadenador), califique el nombre de la tabla de la misma forma.
La misma acción del desencadenador puede definirse para más de una acción del usuario (por ejemplo, INSERT y UPDATE) en la misma instrucción CREATE TRIGGER.
Los desencadenadores INSTEAD OF DELETE/UPDATE no pueden definirse en una tabla con una clave externa definida en cascada en la acción DELETE/UPDATE.
En un desencadenador se puede especificar cualquier instrucción SET. La opción SET seleccionada permanece en efecto durante la ejecución del desencadenador y, después, vuelve a su configuración anterior.
Cuando se activa un desencadenador, los resultados se devuelven a la aplicación que llama, exactamente igual que con los procedimientos almacenados. Para impedir que se devuelvan resultados a la aplicación debido a la activación de un desencadenador, no incluya las instrucciones SELECT que devuelven resultados ni las instrucciones que realizan una asignación variable en un desencadenador. Un desencadenador que incluya instrucciones SELECT que devuelven resultados al usuario o instrucciones que realizan asignaciones de variables requiere un tratamiento especial; estos resultados devueltos tendrían que escribirse en cada aplicación en la que se permiten modificaciones a la tabla del desencadenador. Si es preciso que existan asignaciones de variable en un desencadenador, utilice una instrucción SET NOCOUNT al principio del mismo para impedir la devolución de cualquier conjunto de resultados.
Una instrucción TRUNCATE TABLE es de hecho una instrucción DELETE, pero no activa un desencadenador porque la operación no registra eliminaciones de filas individuales. Sin embargo, sólo los usuarios con permisos para ejecutar una instrucción TRUNCATE TABLE tienen que ocuparse de cómo sortear un desencadenador de DELETE de esta manera.
La instrucción WRITETEXT, ya se registre o no, no activa un desencadenador.
Las siguientes instrucciones Transact-SQL no están permitidas en un desencadenador DML:
|
ALTER DATABASE
|
CREATE DATABASE
|
DROP DATABASE
|
|
LOAD DATABASE
|
LOAD LOG
|
RECONFIGURE
|
|
RESTORE DATABASE
|
RESTORE LOG
|
|
Además, las siguientes instrucciones Transact-SQL no se permiten en el cuerpo de un desencadenador DML cuando éste se utiliza en la tabla o vista que es objeto de la acción desencadenadora.
|
CREATE INDEX (incluidos CREATE SPATIAL INDEX y CREATE XML INDEX)
|
ALTER INDEX
|
DROP INDEX
|
|
DBCC DBREINDEX
|
ALTER PARTITION FUNCTION
|
DROP TABLE
|
|
ALTER TABLE cuando se utiliza para hacer lo siguiente:
-
Agregar, modificar o quitar columnas.
-
Cambiar particiones.
-
Agregar o quitar restricciones de tipo PRIMARY KEY o UNIQUE.
|
|
|
Nota: |
|---|
|
Ya que SQL Server no admite desencadenadores definidos por el usuario en tablas del sistema, se recomienda no crearlos.
|
Los desencadenadores DDL, al igual que los estándar, ejecutan procedimientos almacenados como respuesta a un evento. Pero a diferencia de los desencadenadores estándar, no se ejecutan como respuesta a instrucciones UPDATE, INSERT o DELETE en una tabla o vista. En cambio, se ejecutan principalmente como respuesta a instrucciones de lenguaje de definición de datos (o DDL). Entre ellas se incluyen instrucciones CREATE, ALTER, DROP, GRANT, DENY, REVOKE y UPDATE STATISTICS. Algunos procedimientos almacenados del sistema que ejecutan operaciones de tipo DDL también pueden activar desencadenadores DDL.
Importante: |
|---|
|
Pruebe los desencadenadores DDL para determinar sus respuestas a la ejecución de los procedimientos almacenados del sistema. Por ejemplo, la instrucción CREATE TYPE y el procedimiento almacenado sp_addtype activarán un desencadenador DDL que se crea en un evento CREATE_TYPE. Sin embargo, el procedimiento almacenado sp_rename no activa ningún desencadenador DDL.
|
Para obtener más información acerca de los desencadenadores DDL, vea Desencadenadores DDL.
Los desencadenadores DDL no se activan como respuesta a eventos que afectan a procedimientos almacenados y tablas temporales, ya sean locales o globales.
A diferencia de los desencadenadores DML, los desencadenadores DDL no tienen como ámbito los esquemas. Por tanto, OBJECT_ID, OBJECT_NAME, OBJECTPROPERTY y OBJECTPROPERTYEX no se pueden utilizar para efectuar consultas en metadatos sobre desencadenadores DDL. Utilice en su lugar las vistas de catálogo. Para obtener más información, vea Obtener información acerca de los desencadenadores DDL.
Nota: |
|---|
|
Los desencadenadores DDL con ámbito en el servidor aparecen en el Explorador de objetos de SQL Server Management Studio, en la carpeta Triggers. Dicha carpeta se encuentra en la carpeta Server Objects. Los desencadenadores DDL con ámbito en la base de datos aparecen en la carpeta Database Triggers. Esta carpeta se encuentra en la carpeta Programación de la base de datos correspondiente.
|
Devolver resultados
Se quitará la capacidad de devolver resultados desde los desencadenadores en una futura versión de SQL Server. Los desencadenadores que devuelven conjuntos de resultados pueden provocar comportamientos inesperados en aplicaciones que no están diseñadas para trabajar con ellos. Evite la devolución de conjuntos de resultados desde desencadenadores en los nuevos trabajos de desarrollo y piense en modificar las aplicaciones que la usan actualmente. Para evitar que los desencadenadores devuelvan conjuntos de resultados, establezca la opción No permitir resultados de desencadenadores en 1.
Los desencadenadores LOGON impiden que se devuelvan conjuntos de resultados y este comportamiento no se puede configurar. Si un desencadenador LOGON genera un conjunto de resultados, no se puede ejecutar y se rechazará el intento de iniciar sesión activado por el desencadenador.
Desencadenadores múltiples
SQL Server permite que se creen varios desencadenadores para cada evento DML, DDL o LOGON. Por ejemplo, si se ejecuta CREATE TRIGGER FOR UPDATE para una tabla que ya tiene un desencadenador UPDATE, se creará un desencadenador de actualización adicional. En las versiones anteriores de SQL Server, sólo se permitía un desencadenador por cada evento de modificación (INSERT, UPDATE, DELETE) en cada tabla.
Nota: |
|---|
|
Con un nivel de compatibilidad de 70, el comportamiento predeterminado de CREATE TRIGGER es agregar desencadenadores adicionales a los ya existentes si los nombres de desencadenadores son distintos. Si el nombre de los desencadenadores es el mismo, SQL Server devuelve un mensaje de error. Sin embargo, si el nivel de compatibilidad es igual o menor que 65, cualquier desencadenador creado con la instrucción CREATE TRIGGER substituirá a los desencadenadores existentes del mismo tipo, incluso si los nombres de los desencadenadores son distintos. Para obtener más información, vea sp_dbcmptlevel (Transact-SQL).
|
Desencadenadores recursivos
SQL Server permite también la invocación recursiva de desencadenadores cuando el valor RECURSIVE_TRIGGERS está habilitado mediante ALTER DATABASE.
Los desencadenadores recursivos permiten dos tipos de repetición:
-
Repetición indirecta
Con la repetición indirecta, una aplicación actualiza la tabla T1. Así se activa el desencadenador TR1 para actualizar la tabla T2. En esta situación, el desencadenador T2 activa y actualiza la tabla T1.
-
Repetición directa
Con la repetición directa, una aplicación actualiza la tabla T1. Así se activa el desencadenador TR1 para actualizar la tabla T1. Debido a que la tabla T1 se ha actualizado, el desencadenador TR1 se activa de nuevo, y así sucesivamente.
Este ejemplo utiliza ambas repeticiones de desencadenador, directa e indirecta. Suponga que en la tabla T1 se han definido dos desencadenadores de actualización, TR1 y TR2. El desencadenador TR1 actualiza la tabla T1 recursivamente. Una instrucción UPDATE ejecuta cada TR1 y TR2 una vez. Además, la ejecución de TR1 desencadena la ejecución de TR1 (recursivamente) y TR2. Las tablas inserted y deleted de un desencadenador específico contienen filas que corresponden sólo a la instrucción UPDATE que invocó al desencadenador.
Nota: |
|---|
|
El comportamiento anterior sólo se produce si el valor RECURSIVE_TRIGGERS está habilitado mediante ALTER DATABASE. No hay un orden definido en el que se ejecuten los distintos desencadenadores definidos de un evento específico. Cada desencadenador debe ser independiente.
|
Deshabilitar RECURSIVE_TRIGGERS sólo evita las repeticiones directas. Para deshabilitar la repetición indirecta, establezca la opción nested triggers del servidor en 0 con sp_configure.
Si alguno de los desencadenadores ejecuta una instrucción ROLLBACK TRANSACTION, no se ejecuta ningún desencadenador posterior, independientemente del nivel de anidamiento.
Desencadenadores anidados
Los desencadenadores pueden anidarse hasta un máximo de 32 niveles. Si un desencadenador cambia una tabla en la que hay otro desencadenador, el segundo se activa y puede, entonces, llamar a un tercero, y así sucesivamente. Si algún desencadenador de la cadena causa un bucle infinito, el nivel de anidamiento se habrá sobrepasado, con lo que se cancela el desencadenador. Para deshabilitar los desencadenadores anidados, establezca la opción nested triggers de sp_configure en 0 (desactivada). La configuración predeterminada permite desencadenadores anidados. Si los desencadenadores anidados están desactivados, los desencadenadores recursivos también se deshabilitan, independientemente del valor de RECURSIVE_TRIGGERS establecido mediante ALTER DATABASE.
Nota: |
|---|
|
Cuando un desencadenador Transact-SQL ejecuta código administrado haciendo referencia a una rutina, un tipo o agregado CLR, esta referencia cuenta como un nivel para el límite de anidamiento de 32 niveles. Los métodos invocados desde el código administrado no cuentan para este límite.
|
Resolución diferida de nombres
SQL Server permite que los procedimientos almacenados, desencadenadores y procesos por lotes de Transact-SQL hagan referencia a tablas que no existen en el momento de la compilación. Esta capacidad se denomina resolución diferida de nombres. Sin embargo, si los procedimientos almacenados, desencadenadores y procesos por lotes de Transact-SQL hacen referencia a una tabla definida en el procedimiento almacenado o desencadenador, se emitirá una advertencia en el momento de la creación sólo si el valor de nivel de compatibilidad se establece en 65. Si se utiliza un proceso por lotes, la advertencia se emite en el momento de la compilación. Si la tabla a la que se hace referencia no existe, se devuelve un mensaje de error en tiempo de ejecución. Para obtener más información, vea Resolución diferida de nombres y compilación.