Estoy trabajando en SQL Server 2008 R2.
Tengo un beneficio de tabla que tiene un desencadenador DESPUÉS DE INSERTAR, ACTUALIZAR, llamado tiu_benefit .
Quiero escribir una declaración de ACTUALIZACIÓN para que esta tabla actualice 1 fila, pero no quiero que se active su desencadenante. Sé que puedo desactivar el activador antes de ACTUALIZAR y luego activar el activador después de ACTUALIZAR:
DISABLE TRIGGER tiu_benefit ON benefit;
GO
UPDATE benefit SET editor = 'srh' where benefit_id = 9876
GO
ENABLE TRIGGER tiu_benefit ON benefit;
GO
Pero este activador de activación y desactivación afectará a todos los usuarios conectados actualmente. Por lo tanto, existe la posibilidad de que otro usuario ejecute una ACTUALIZACIÓN / INSERCIÓN mientras mi secuencia de comandos está deshabilitada, lo que no es bueno. Es por eso que solo quiero deshabilitar y habilitar el disparador para mi sesión actual. ¿Es posible? En caso afirmativo, por favor diga cómo.
Gracias
Respuestas:
Hice algunas pruebas sobre esto y creo que estaría bien si ejecuta su proceso en una sola transacción.
En mis pruebas, solo resalté y ejecuté el
BEGIN TRANSACTION
y elDISABLE TRIGGER
primero. Entonces abrí un nuevo (segundo) ventana de consulta y trató de ejecutar varias instrucciones DML (SELECT
,INSERT
,UPDATE
DELETE
) en contra de la tabla base. Todos los intentos de acceder a la tabla base en la segunda ventana de consulta esperaron en los bloqueos mantenidos por la ventana con la transacción explícita. Una vez que comprometí (o revertí) mi transacción explícita, la segunda ventana pudo acceder a la tabla.fuente
benefit_id
:)Para resolver su problema, debemos adoptar un enfoque programático del problema. Hay dos rutas que puedes seguir aquí. La razón por la que necesita estos enfoques es porque no puede deshabilitar un desencadenador para una declaración particular, solo puede deshabilitarse para la totalidad de la tabla.
Opción 1: Context_Info ()
Samuel Vanga en MS SQL Tips tuvo un gran ejemplo:
Ahora, cuando Samuel no quiere que se ejecute el disparador, usan esto:
Context_Info
utiliza las siguientes vistas del sistema para obtener información sobre la sesión actual:sys.dm_exec_requests
sys.dm_exec_sessions
sys.sysprocesses
La ideología aquí es que la cadena binaria que está configurando está expuesta solo a la sesión actual, por lo que cuando el disparador se ejecute durante su sesión, verá el alcance y la configuración variable de la
Context_info
función y saltará a la parte de escape del disparador en lugar.Opción 2: tabla temporal
Itzik Ben-Gan tiene una gran solución en su libro "Inside Microsoft SQL Server 2008 Programación T-SQL: Programación T-SQL", que también se encuentra en su libro posterior T-SQL Querying . El principal problema con esto sobre la
context_info
función es la sobrecarga menor de TempDB.Para estropear la sorpresa pero no arruinar la trama de los libros (sentí que vale la pena comprarlos y leerlos), alterará su gatillo.
Su disparador debe realizar una verificación para una tabla temporal. Si la tabla temporal existe, el desencadenador debe saber que finaliza y no realiza las acciones.
En la declaración de actualización que desea realizar, cree primero la tabla temporal. Se verá en la misma transacción que el activador y hará que el activador ignore su estado de cuenta.
Ejemplo de disparador:
Ejemplo de declaración inicial cuando no desea que se ejecute el desencadenador:
Poniéndolo por completo para su ejemplo:
fuente
context_info
usaroriginal_login()
para decirle al gatillo que nunca se ejecute si una persona específica está presionando el gatillo.Yo usaría cualquiera
CONTEXT_INFO
o el más nuevoSESSION_CONTEXT
. Ambos son valores basados en sesión.CONTEXT_INFO
Es unVARBINARY(128)
valor único . Esto ha estado disponible desde que al menos SQL Server 2000.CONTEXT_INFO
es visible para cualquier persona,VIEW SERVER STATE
ya que es un campo devuelto por elsys.dm_exec_sessions
DMV. He usado este antes y funciona bastante bien.Establecer mediante SET CONTEXT_INFO
Obtener mediante CONTEXT_INFO () o sys.dm_exec_sessions
Dependiendo del tipo de valor que está almacenando
CONTEXT_INFO
, hay algunos matices a tener en cuenta. Cubro eso en la siguiente publicación de blog:¿Por qué CONTEXT_INFO () no devuelve el valor exacto establecido por SET CONTEXT_INFO?
Session_context es un par de
SQL_VARIANT
valores clave / valor . Esto se introdujo en SQL Server 2016. La separación de valores para diferentes propósitos es bastante agradable. Session_context solo es visible para la sesión actual.Establezca este valor a través de sp_set_session_context
Obtenga este valor a través de SESSION_CONTEXT
Una cosa a tener en cuenta con respecto a la opción de tabla temporal local e incluso la opción de activación / desactivación de activación: ambas requieren cierta cantidad de actividad de bloqueo y de registro de transferencia. Ambas opciones aumentan el potencial de contención, aunque sea mínimamente. Las dos opciones de "contexto" deben ser más ligeras / solo de memoria.
fuente