Pregunta

Estoy intentando escribir un disparador en una tabla para evitar la inserción de dos nombres que no están marcados como IsDeleted. Pero la primera parte de la selección contiene el insertado, por lo que la condición siempre es verdadera. Pensé que el uso de la palabra clave FOR hace que el desencadenador se ejecute antes de INSERTION pero en este caso la fila insertada ya está en la tabla. ¿Estoy equivocado o así es como funcionan todos los activadores FOR?

ALTER TRIGGER TriggerName
ON MyTable
FOR INSERT, UPDATE
AS
BEGIN 
    If exist (select [Name] From MyTable WHERE IsDeleted = 0 AND [Name] in (SELECT [Name] FROM INSERTED)
    BEGIN
    RAISERROR ('ERROR Description', 16, 1);
    Rollback;
    END  
END
¿Fue útil?

Solución

FOR se ejecuta después de que se cambian los datos, INSTEAD OF es lo que creo que estás buscando.

EDITAR: según lo indicado por otros, INSTEAD OF se ejecuta en lugar de los datos que está cambiando, por lo tanto, debe insertar los datos si son válidos, en lugar de detener el inserto si no es válido.

Lea esta pregunta para obtener una explicación mucho más detallada de los tipos de disparadores.

SQL Server " DESPUÉS INSERTAR " el activador no ve la fila recién insertada

Otros consejos

FOR es lo mismo que DESPUÉS. si quieres " simular " ANTES de la activación, use INSTEAD OF, advertencia, no es exactamente lo que esperaría en una correcta activación ANTES, es decir, si no proporciona la acción INSTEAD necesaria, sus datos insertados / actualizados podrían perderse / ignorarse.

MSSQL no tiene activador ANTES.

Para SQL Server, FOR ejecuta DESPUÉS del SQL que lo activó.

Desde: http://msdn.microsoft.com/en-us/library/ms189799. aspx

  

PARA | DESPUÉS

     

DESPUÉS especifica que el activador DML   se dispara solo cuando todas las operaciones   especificado en la activación de SQL   declaración se ha ejecutado con éxito.   Todas las acciones referenciales en cascada y   los controles de restricción también deben tener éxito   antes de que se dispare este disparador.

     

DESPUÉS es el valor predeterminado cuando FOR es el   única palabra clave especificada.

     

DESPUÉS de los desencadenantes   no se puede definir en las vistas.

En realidad me he encontrado con un problema similar últimamente, y he encontrado una manera genial de manejarlo. Tenía una tabla que podía tener varias filas para una identificación, pero solo UNA de ellas podría marcarse como primaria.

En SQL Server 2008, podrás hacer un índice único parcial como este:

create unique index IX on MyTable(name) where isDeleted = 0;

Sin embargo, puede lograrlo con un poco más de trabajo en SQL Server 2005. El truco es hacer una vista que muestre solo las filas que no se eliminan, y luego crear un índice agrupado único en él:

 create view MyTableNotDeleted_vw
 with schema_binding /* Must be schema bound to create an indexed view */
 as
 select name 
 from dbo.MyTable /* Have to use dbo. for schema bound views */
 where isDeleted = 0;

 GO

 create unique clustered index IX on MyTableNotDeleted_vw ( name );

¡Esto creará efectivamente una restricción única que solo afectará a las filas que aún no se han eliminado, y probablemente se desempeñará mejor que un disparador personalizado!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top