Dat*_*ger 2 trigger sql-server dml sql-server-2012
我有 2 个插入后触发器和 1 个而不是插入触发器的问题。After Insert 触发器应该执行一些操作,但不会触发这些操作。
当替代触发器触发时,它们的动作 After Triggers 工作正常。
让我解释:
“替代”触发器验证该ID
值是否为 Null。如果是,则触发器在表 ( TRADE_APPR
) 中执行插入操作,填充ID
SQL Server 序列中的值。
当替代触发器执行操作时,插入后触发器也执行它们的操作。
我的而不是插入触发器的代码是这样的:
ALTER TRIGGER [ConfirmMgr].[TG_TRADE_APPR_BER_I]
ON [ConfirmMgr].TRADE_APPR]
INSTEAD OF INSERT
AS
DECLARE
@user_name varchar(50),
@appr_username varchar(50),
@appr_id int,
@v_id int,
@appr_timestamp datetime
BEGIN
SELECT @appr_username = APPR_BY_USERNAME FROM inserted
IF (@appr_username) IS NULL
BEGIN
SELECT @user_name = SUSER_NAME()
UPDATE tbl SET APPR_BY_USERNAME = UPPER(@user_name)
FROM ConfirmMgr.TRADE_APPR tbl
INNER JOIN inserted i ON tbl.ID = i.ID
END
SELECT @appr_id = i.ID FROM inserted i
IF (@appr_id) IS NULL
BEGIN
INSERT ConfirmMgr.TRADE_APPR
SELECT
NEXT VALUE FOR ConfirmMgr.SEQ_TRADE_APPR,
i.TRADE_ID,
i.APPR_FLAG,
ISNULL(i.APPR_TIMESTAMP_GMT,GETDATE()),
ISNULL(i.APPR_BY_USERNAME, UPPER(SUSER_NAME()))
FROM inserted i
END
RETURN
END
Run Code Online (Sandbox Code Playgroud)
由于您可以检查我的代码,而不是触发器验证 如果 user_name 或 ID 为空,则执行操作。
当您发送空值时,触发器工作正常,并且 After 触发器也能正常工作。
关键是当您发送包含 ID 的正确值时,插入操作不会保存记录,因为这不会插入记录,并且插入后触发器不会执行它们的操作。
我知道你发送了正确的值,像这样的触发器而不是不应该执行或阻止某些事情。
我做了一个测试,禁用了替代插入触发器,记录被保存,插入后触发器工作正常。
我的问题是:当您发送权限值时,为什么“替代插入”触发器会影响插入操作?
下面是我在插入后触发器之一中的代码
谢谢你的建议
ALTER TRIGGER ConfirmMgr.TG_TRADE_APPR_AER_I
ON ConfirmMgr.TRADE_APPR
AFTER INSERT
AS
/******************************************************************************
*
* AUTHOR: JAVIER MONTERO - 08/19/2015
* DB: SQL SERVER 2012 OR HIGHER
* VERSION: 1.0
* DESCRIPTION: TRIGGER FOR UPDATE THE FIELD FINAL_APPROVAL_FLAG,
FINAL_APPROVAL_TIMESTAMP_GMT AND TRANSACTION_SEQ
IN TABLE TRADE_SUMMARY WHEN A INSERT ACTION IS FIRED IN
TRADE_APPR TABLE
* DEPENDECIES: TABLE TRADE_SUMMARY AND SEQUENCE SEQ_TRADE_SUMMARY_TRANSACTION
*
*******************************************************************************/
DECLARE
@v_id int
BEGIN
/*The process collect the trade_id that is coming in the inserted values*/
SELECT @v_id = ts.TRADE_ID
FROM ConfirmMgr.TRADE_SUMMARY ts
JOIN inserted i
ON ts.TRADE_ID = i.TRADE_ID
print cast(@v_id as varchar)
/*The trade_id saved in the local variable @v_id is validated is different to Null*/
IF (@v_id) IS NOT NULL
BEGIN
/*Finally we update the fields FINAL_APPROVAL_FLAG, FINAL_APPROVAL_TIMESTAMP_GMT and TRANSACTION_SEQ
in the table TRADE_SUMMARY also it use a SQL Sequence to set the TRANSACTION SEQUENCE value in the table */
UPDATE ts
SET ts.FINAL_APPROVAL_FLAG = i.APPR_FLAG,
ts.FINAL_APPROVAL_TIMESTAMP_GMT = i.APPR_TIMESTAMP_GMT,
ts.TRANSACTION_SEQ = NEXT VALUE FOR ConfirmMgr.SEQ_TRADE_SUMMARY_TRANSACTION
FROM ConfirmMgr.TRADE_SUMMARY ts
INNER JOIN inserted i
ON ts.TRADE_ID = i.TRADE_ID
END
END
Run Code Online (Sandbox Code Playgroud)
一个INSTEAD OF INSERT
触发器执行的行动,而不是什么原本INSERT
会做的。
在您的代码中,如果@appr_username
或@appr_id
为 NULL,则对基表进行某种更改(插入或更新)。
否则,触发器不会执行任何操作(不影响行),因此AFTER
会跳过触发器。毕竟,SQL Server 认为,如果INSTEAD OF
触发器什么都不做,触发器也不AFTER
能做任何事情,对吧?
请注意,如果服务器配置选项nested triggers
(如Allow Triggers to Fire Others
SSMS 高级服务器属性选项卡中所示)设置为 1(默认值),您也会得到一些非常令人困惑的行为。
从该链接:
嵌套触发器选项控制 AFTER 触发器是否可以级联。即,执行启动另一个触发器的操作,启动另一个触发器,依此类推。当嵌套触发器设置为 0 时,AFTER 触发器不能级联。当嵌套触发器设置为 1(默认值)时,AFTER 触发器可以级联到多达 32 个级别。无论此选项的设置如何,INSTEAD OF 触发器都可以嵌套。