MSI*_*SIL 155 t-sql sql-server triggers
我需要在表A上编写一个Insert,Update Trigger,它将删除表B中的所有行,其中一列(比如Desc)的值类似于表A列中插入/更新的值(比如Col1).我将如何编写它以便我可以处理Update和Insert案例.如何确定是否为更新或插入执行了触发器.
gbn*_*gbn 160
如果是MS SQL Server ......
触发器具有特殊INSERTED和DELETED表格来跟踪"之前"和"之后"数据.所以你可以使用类似的东西IF EXISTS (SELECT * FROM DELETED)来检测更新.您只有DELETED更新中的行,但总是有行INSERTED.
在CREATE TRIGGER中查找"inserted"
编辑,2011年11月23日
评论后,这个答案仅适用于INSERTED和UPDATED触发.
显然,INSERTED正如我上面所说,DELETE触发器不能有"总是在行中"
net*_*rog 121
CREATE TRIGGER dbo.TableName_IUD
ON dbo.TableName
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
SET NOCOUNT ON;
--
-- Check if this is an INSERT, UPDATE or DELETE Action.
--
DECLARE @action as char(1);
SET @action = 'I'; -- Set Action to Insert by default.
IF EXISTS(SELECT * FROM DELETED)
BEGIN
SET @action =
CASE
WHEN EXISTS(SELECT * FROM INSERTED) THEN 'U' -- Set Action to Updated.
ELSE 'D' -- Set Action to Deleted.
END
END
ELSE
IF NOT EXISTS(SELECT * FROM INSERTED) RETURN; -- Nothing updated or inserted.
...
END
Run Code Online (Sandbox Code Playgroud)
Mik*_*Vee 78
如果您运行删除任何内容的删除语句,其中许多建议都不会考虑.
假设您尝试删除ID等于表中不存在的某个值的位置.
仍会调用您的触发器,但"已删除"或"已插入"表中没有任何内容.
使用它是安全的:
--Determine if this is an INSERT,UPDATE, or DELETE Action or a "failed delete".
DECLARE @Action as char(1);
SET @Action = (CASE WHEN EXISTS(SELECT * FROM INSERTED)
AND EXISTS(SELECT * FROM DELETED)
THEN 'U' -- Set Action to Updated.
WHEN EXISTS(SELECT * FROM INSERTED)
THEN 'I' -- Set Action to Insert.
WHEN EXISTS(SELECT * FROM DELETED)
THEN 'D' -- Set Action to Deleted.
ELSE NULL -- Skip. It may have been a "failed delete".
END)
Run Code Online (Sandbox Code Playgroud)
特别感谢@KenDog和@Net_Prog的回答.
我从他们的脚本中构建了这个.
Sat*_*Sat 17
我正在使用以下内容,它还正确检测删除任何内容的删除语句:
CREATE TRIGGER dbo.TR_TableName_TriggerName
ON dbo.TableName
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
SET NOCOUNT ON;
IF NOT EXISTS(SELECT * FROM INSERTED)
-- DELETE
PRINT 'DELETE';
ELSE
BEGIN
IF NOT EXISTS(SELECT * FROM DELETED)
-- INSERT
PRINT 'INSERT';
ELSE
-- UPDATE
PRINT 'UPDATE';
END
END;
Run Code Online (Sandbox Code Playgroud)
小智 11
经过大量搜索后,我找不到单个SQL Server触发器的确切示例,该触发器处理触发器操作INSERT,UPDATE和DELETE的所有(3)三个条件.我终于找到了一行文字,其中谈到了当发生DELETE或UPDATE时,公共DELETED表将包含这两个动作的记录.基于该信息,我创建了一个小的Action例程,用于确定触发器被激活的原因.当在INSERT与UPDATE触发器上同时存在公共配置和特定操作时,有时需要此类型的接口.在这些情况下,为UPDATE和INSERT创建单独的触发器将成为维护问题.(即两个触发器是否都已正确更新以进行必要的常见数据算法修复?)
为此,我想提供以下多触发事件代码片段,用于在Microsoft SQL Server的一个触发器中处理INSERT,UPDATE,DELETE.
CREATE TRIGGER [dbo].[INSUPDDEL_MyDataTable]
ON [dbo].[MyDataTable] FOR INSERT, UPDATE, DELETE
AS
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with caller queries SELECT statements.
-- If an update/insert/delete occurs on the main table, the number of records affected
-- should only be based on that table and not what records the triggers may/may not
-- select.
SET NOCOUNT ON;
--
-- Variables Needed for this Trigger
--
DECLARE @PACKLIST_ID varchar(15)
DECLARE @LINE_NO smallint
DECLARE @SHIPPED_QTY decimal(14,4)
DECLARE @CUST_ORDER_ID varchar(15)
--
-- Determine if this is an INSERT,UPDATE, or DELETE Action
--
DECLARE @Action as char(1)
DECLARE @Count as int
SET @Action = 'I' -- Set Action to 'I'nsert by default.
SELECT @Count = COUNT(*) FROM DELETED
if @Count > 0
BEGIN
SET @Action = 'D' -- Set Action to 'D'eleted.
SELECT @Count = COUNT(*) FROM INSERTED
IF @Count > 0
SET @Action = 'U' -- Set Action to 'U'pdated.
END
if @Action = 'D'
-- This is a DELETE Record Action
--
BEGIN
SELECT @PACKLIST_ID =[PACKLIST_ID]
,@LINE_NO = [LINE_NO]
FROM DELETED
DELETE [dbo].[MyDataTable]
WHERE [PACKLIST_ID]=@PACKLIST_ID AND [LINE_NO]=@LINE_NO
END
Else
BEGIN
--
-- Table INSERTED is common to both the INSERT, UPDATE trigger
--
SELECT @PACKLIST_ID =[PACKLIST_ID]
,@LINE_NO = [LINE_NO]
,@SHIPPED_QTY =[SHIPPED_QTY]
,@CUST_ORDER_ID = [CUST_ORDER_ID]
FROM INSERTED
if @Action = 'I'
-- This is an Insert Record Action
--
BEGIN
INSERT INTO [MyChildTable]
(([PACKLIST_ID]
,[LINE_NO]
,[STATUS]
VALUES
(@PACKLIST_ID
,@LINE_NO
,'New Record'
)
END
else
-- This is an Update Record Action
--
BEGIN
UPDATE [MyChildTable]
SET [PACKLIST_ID] = @PACKLIST_ID
,[LINE_NO] = @LINE_NO
,[STATUS]='Update Record'
WHERE [PACKLIST_ID]=@PACKLIST_ID AND [LINE_NO]=@LINE_NO
END
END
Run Code Online (Sandbox Code Playgroud)
我相信嵌套ifs有点令人困惑,并且:
扁平比嵌套好[Python的禅]
;)
DROP TRIGGER IF EXISTS AFTER_MYTABLE
GO
CREATE TRIGGER dbo.AFTER_MYTABLE ON dbo.MYTABLE AFTER INSERT, UPDATE, DELETE
AS BEGIN
--- FILL THE BEGIN/END SECTION FOR YOUR NEEDS.
SET NOCOUNT ON;
IF EXISTS(SELECT * FROM INSERTED) AND EXISTS(SELECT * FROM DELETED)
BEGIN PRINT 'UPDATE' END
ELSE IF EXISTS(SELECT * FROM INSERTED) AND NOT EXISTS(SELECT * FROM DELETED)
BEGIN PRINT 'INSERT' END
ELSE IF EXISTS(SELECT * FROM DELETED) AND NOT EXISTS(SELECT * FROM INSERTED)
BEGIN PRINT 'DELETED' END
ELSE BEGIN PRINT 'NOTHING CHANGED'; RETURN; END -- NOTHING
END
Run Code Online (Sandbox Code Playgroud)
小智 7
Declare @Type varchar(50)='';
IF EXISTS (SELECT * FROM inserted) and EXISTS (SELECT * FROM deleted)
BEGIN
SELECT @Type = 'UPDATE'
END
ELSE IF EXISTS(SELECT * FROM inserted)
BEGIN
SELECT @Type = 'INSERT'
END
ElSE IF EXISTS(SELECT * FROM deleted)
BEGIN
SELECT @Type = 'DELETE'
END
Run Code Online (Sandbox Code Playgroud)
虽然我也喜欢@Alex 发布的答案,但我为上面的@Graham 解决方案提供了这种变化
这仅使用 INSERTED 和 UPDATED 表中的记录存在,而不是使用 COLUMNS_UPDATED 进行第一次测试。它还为偏执的程序员提供了解脱,因为它知道已经考虑了最后一个案例......
declare @action varchar(4)
IF EXISTS (SELECT * FROM INSERTED)
BEGIN
IF EXISTS (SELECT * FROM DELETED)
SET @action = 'U' -- update
ELSE
SET @action = 'I' --insert
END
ELSE IF EXISTS (SELECT * FROM DELETED)
SET @action = 'D' -- delete
else
set @action = 'noop' --no records affected
--print @action
Run Code Online (Sandbox Code Playgroud)
您将获得 NOOP,其中包含如下语句:
update tbl1 set col1='cat' where 1=2
Run Code Online (Sandbox Code Playgroud)
小智 5
试试这个..
ALTER TRIGGER ImportacionesGS ON dbo.Compra
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
-- idCompra is PK
DECLARE @vIdCompra_Ins INT,@vIdCompra_Del INT
SELECT @vIdCompra_Ins=Inserted.idCompra FROM Inserted
SELECT @vIdCompra_Del=Deleted.idCompra FROM Deleted
IF (@vIdCompra_Ins IS NOT NULL AND @vIdCompra_Del IS NULL)
Begin
-- Todo Insert
End
IF (@vIdCompra_Ins IS NOT NULL AND @vIdCompra_Del IS NOT NULL)
Begin
-- Todo Update
End
IF (@vIdCompra_Ins IS NULL AND @vIdCompra_Del IS NOT NULL)
Begin
-- Todo Delete
End
END
Run Code Online (Sandbox Code Playgroud)
DECLARE @ActionType CHAR(6);
SELECT @ActionType = COALESCE(CASE WHEN EXISTS(SELECT * FROM INSERTED)
AND EXISTS(SELECT * FROM DELETED) THEN 'UPDATE' END,
CASE WHEN EXISTS(SELECT * FROM DELETED) THEN 'DELETE' END,
CASE WHEN EXISTS(SELECT * FROM INSERTED) THEN 'INSERT' END);
PRINT @ActionType;
Run Code Online (Sandbox Code Playgroud)