繁体   English   中英

输出子句VS触发器

[英]output clause VS triggers

在我们的数据库上,大多数表都有dbupddate字段,该字段指示在行上应用的最后一次INSERTUPDATEdatetime时间。

为了避免该字段具有错误的值,存在触发器(有时是AFTER ,有时是INSTEAD OF ),这些触发器确保最后该值是正确的,而不是其他人可能尝试写入该字段的“手动”其他值。

现在,我正在执行一条更新语句(执行MERGE ),并且我想拥有一个包含该字段的OUTPUT子句。 正如我在相应的MS文章中所读到OUTPUT忽略触发器。

有什么解决方法可以让OUTPUT在触发器之后返回dbupddate具有的值? 我不想进行另一个查询来绘制信息,因为我不能保证在这些查询之间的瞬间,另一个用户的第三个查询可能并没有改变所有事情。


遵循Larnu的建议后的结果

我运行了提供的示例,唯一的例外是将updatetime字段的default值更改为convert(datetime2,'1900-01-01')因此我可能会有所理解。 我运行了4个查询中的每个查询,然后分别从它们各自的表中进行选择,并比较了updatetime值:

INSERT INTO dbo.Sample1 (Someint)
OUTPUT inserted.*
INTO @inserted
SELECT 1;

SELECT 'Sample1 INSERT',*
FROM @inserted; -- 1900-01-01 00:00:00.000000
select * from Sample1  -- 2018-11-05 13:12:13.141580

我猜这里的输出将忽略触发器,并返回在after触发器生效之前插入的默认值。

DECLARE @inserted table (ID int, Someint int, updatedtime datetime2(6))
INSERT INTO dbo.Sample2 (Someint)
OUTPUT inserted.*
INTO @inserted
SELECT 1;

SELECT 'Sample2 INSERT',* --1900-01-01 00:00:00.000000
FROM @inserted;
select * from Sample2 --2018-11-05 13:12:35.580190

相同。 现在疯狂的部分来了。 我把插入和删除的日期都画出来了:

DECLARE @updated table (ID int, Someint int, ins_updatedtime datetime2(6),del_updatedtime datetime2(6))
UPDATE dbo.Sample1 
SET Someint = 2
OUTPUT Inserted.*,Deleted.updatetime
INTO @updated;

SELECT 'Sample1 UPDATE',*
FROM @updated;   --Sample1 UPDATE   1   2   2018-11-05 13:30:01.348490  2018-11-05 13:30:01.348490
select * from Sample1  -- 1 2   2018-11-05 13:31:31.851047


DECLARE @updated table (ID int, Someint int, ins_updatedtime datetime2(6),del_updatedtime datetime2(6))
UPDATE dbo.Sample2
SET Someint = 2
OUTPUT Inserted.*,Deleted.updatetime
INTO @updated;

SELECT 'Sample2 UPDATE',* -- Sample2 UPDATE 1   2   2018-11-05 13:30:20.286422  2018-11-05 13:30:20.286422
FROM @updated;
select * from Sample2 --1   2   2018-11-05 13:31:51.679726

因此,在update情况下,默认值不存在,但实际表和查询输出中的值却不同。 我既不知道如何使这些值相同,也不知道更新案例中的日期时间到底发生了什么。

您可以将OUTPUTTRIGGER一起使用,但也必须使用INTO子句。 取得这些样本表和触发器:

CREATE TABLE dbo.Sample1 (SomeID int IDENTITY(1,1),
                          Someint int,
                          updatetime datetime2(6) DEFAULT SYSDATETIME());
CREATE TABLE dbo.Sample2 (SomeID int IDENTITY(1,1),
                          Someint int,
                          updatetime datetime2(6) DEFAULT SYSDATETIME());

GO

CREATE TRIGGER dbo.AfterInsertUdpate ON dbo.Sample1
AFTER INSERT, UPDATE
AS
    UPDATE S
    SET S.updatetime = SYSDATETIME()
    FROM dbo.Sample1 S
         JOIN Inserted i ON S.SomeID = i.SomeID;
GO

CREATE TRIGGER dbo.InsteadInsert ON dbo.Sample2
INSTEAD OF INSERT
AS
    INSERT INTO dbo.Sample2 (Someint,
                             updatetime)
    SELECT Someint, SYSDATETIME()
    FROM Inserted;

GO

CREATE TRIGGER dbo.InsteadUpdate ON dbo.Sample2
INSTEAD OF UPDATE
AS
    UPDATE S
    SET S.Someint = i.Someint,
        S.updatetime = SYSDATETIME()
    FROM dbo.Sample2 S
         JOIN Inserted i ON S.SomeID = i.SomeID;

如果我们运行以下SQL,您将得到一个错误:

INSERT INTO dbo.Sample1 (Someint)
OUTPUT inserted.*
SELECT 1;

消息334,级别16,状态1,第44行,如果该语句包含不带INTO子句的OUTPUT子句,则DML语句的目标表'dbo.Sample1'无法具有任何已启用的触发器。

该错误为您提供了提示,请使用INTO子句。 因此,您可以执行以下操作:

DECLARE @inserted table (ID int, Someint int, updatedtime datetime2(6))

INSERT INTO dbo.Sample1 (Someint)
OUTPUT inserted.*
INTO @inserted
SELECT 1;

SELECT 'Sample1 INSERT',*
FROM @inserted;

这对INSERTUPDATE ,无论是AFTER还是INSTEAD OF

DECLARE @inserted table (ID int, Someint int, updatedtime datetime2(6))
INSERT INTO dbo.Sample2 (Someint)
OUTPUT inserted.*
INTO @inserted
SELECT 1;

SELECT 'Sample2 INSERT',*
FROM @inserted;

GO
DECLARE @updated table (ID int, Someint int, updatedtime datetime2(6))
UPDATE dbo.Sample1 
SET Someint = 2
OUTPUT Inserted.*
INTO @updated;

SELECT 'Sample1 UPDATE',*
FROM @updated;

GO
DECLARE @updated table (ID int, Someint int, updatedtime datetime2(6))
UPDATE dbo.Sample2
SET Someint = 2
OUTPUT Inserted.*
INTO @updated;

SELECT 'Sample2 UPDATE',*
FROM @updated;
GO

--Clean up
DROP TABLE dbo.Sample1;
DROP TABLE dbo.Sample2;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM