¿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?
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.)
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
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.
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.
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