¿Cómo puedo editar los valores de una INSERCIÓN en un desencadenador en SQL Server?


Tengo la tabla Tb

ID | Name   | Desc
-------------------------
 1 | Sample | sample desc

Quiero crear un disparador en INSERT que cambiará el valor de la inserción Desc, por ejemplo:

INSERT INTO Tb(Name, Desc) VALUES ('x', 'y')

Dará lugar a

ID | Name   | Desc
-------------------------
 1 | Sample | sample desc
 2 | x      | Y edited

En el ejemplo anterior obtuve el valor de la inserción Desc lo cambié a mayúscula y agregué edited al final.

Eso es lo que necesito, obtener el Desc que se está insertando y modificarlo.

¿Cómo puedo hacer eso?

¿Es mejor manejarlo después del inserto con una actualización? ¿O hacer un desencadenador con EN LUGAR DE INSERTAR y modificarlo cada vez que cambie la estructura de la tabla?

Author: Vadzim, 2010-08-27

4 answers

Utilice un disparador de inserción después. Unir desde la pseudo tabla inserted a Tb en la clave primaria. A continuación, actualice los valores de desc. Algo como: (Pero no puede compilar)

CREATE TRIGGER TbFixTb_Trg 
ON  Tb  
AFTER INSERT 
AS  
BEGIN 
    UPDATE Tb
    SET DESC = SomeTransformationOf(i.DESC)
    FROM Tb
    INNER JOIN inserted i on i.Id = Tb.Id
END  
GO

Este disparador ocurre después de que el insert haya sucedido, pero antes de que se complete la instrucción insert. Por lo tanto, los nuevos valores incorrectos ya se colocan en la tabla de destino. Este disparador no tendrá que cambiar a medida que se agreguen columnas, se eliminen, etc.

Advertencia Las restricciones de integridad se aplican antes del después el gatillo se dispara. Por lo tanto, no puede poner una restricción de verificación para hacer cumplir la forma adecuada de DESC. Porque eso causaría que la declaración fallara antes de que el disparador tuviera la oportunidad de arreglar algo. (Por favor revise este párrafo antes de confiar en él. Ha pasado un tiempo desde que escribí un disparador.)

 33
Author: Shannon Severance,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-11 20:47:38

No estoy seguro de dónde va a obtener el nuevo valor real para desc, pero asumo que lo está obteniendo de otra tabla o algo así. Pero probablemente tenga una razón para querer hacerlo de esta manera, así que a continuación hay un ejemplo de cómo lo haría.

Lo que quieres se llama un disparador EN LUGAR DE INSERTAR, se dispara en lugar de un insert en la tabla con lo que cada lógica que le das.

CREATE TRIGGER trgUpdateDesc
ON  Tb 
INSTEAD OF INSERT
AS 
BEGIN
    SET NOCOUNT ON;
    INSERT INTO Tb (Name, [Desc])
    SELECT Name, [Desc] + 'edited'
    FROM inserted
END 
GO

He codificado la palabra 'editado' allí, ya que no estoy seguro de dónde quieres obtener el valor, pero puede reemplazarlo fácilmente con una variable o un valor de otra tabla.

Oh también asegúrese de poner el [] alrededor Desc, ya que es una palabra clave en sql server (significa descendente)

¡Espero que eso ayude!

Editar:

Si desea hacerlo un poco más robusto para que no dependa tanto de la estructura de la tabla, podría usar un disparador DE INSERCIÓN POSTERIOR para actualizar ese campo de esta manera.

CREATE TRIGGER [dbo].[trgUpdateDesc]
   ON  [dbo].[Tb] 
   AFTER INSERT
AS 
BEGIN
    SET NOCOUNT ON;
    UPDATE Tb
    SET [Desc] = UPPER(inserted.[Desc]) +  ' Edited'
    FROM inserted INNER JOIN Tb On inserted.id = Tb.id
END 
 25
Author: JonVD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-27 00:40:17

La tabla Temp puede ayudar a usar INSTEAD OF INSERT trigger mientras evita enumerar explícitamente todas las columnas de la tabla no relacionadas:

CREATE TRIGGER trgUpdateDesc
    ON Tb 
    INSTEAD OF INSERT
AS 
BEGIN
    SET NOCOUNT ON;
    select * into #tmp from inserted;
    UPDATE #tmp SET Desc = Desc + 'edited' --where ...;
    insert into Tb select * from #tmp;
    drop table #tmp;
END 

Este código no necesitará ser corregido cuando se agreguen nuevas columnas a la tabla.

Pero tenga cuidado con algunos gastos generales adicionales de las tablas temporales.

También tenga en cuenta que SQL Server dispara una vez para operaciones DML masivas y debe manejar correctamente insertos de varias filas.

 8
Author: Vadzim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:32

Es posible que desee mirar los disparadores INSTEAD OF.

CREATE TRIGGER Tb_InsteadTrigger on Tb
INSTEAD OF INSERT
AS
BEGIN
...

Esto le permitirá manipular los datos antes de que entren en la tabla. El desencadenador es responsable de insertar los datos en la tabla.

 3
Author: bobs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-26 23:02:17