Sql 输出子句VS触发器

Sql 输出子句VS触发器,sql,sql-server,tsql,database-trigger,output-clause,Sql,Sql Server,Tsql,Database Trigger,Output Clause,在我们的数据库中,大多数表都有一个dbupddate字段,该字段指示最后一行应用的INSERT或UPDATE的datetime 为了避免此字段具有错误的值,存在触发器(有时在之后,有时是在之后,有时是在而不是在)以确保最终值是正确的,而不是有人试图写入该字段的任何“手动”其他值 现在我正在执行一个update语句(实际上是MERGE),我希望有一个包含该字段的OUTPUT子句。正如我在书中读到的,OUTPUT忽略触发器 在触发器之后,是否有任何变通方法让输出返回值dbupddatehas?我不想

在我们的数据库中,大多数表都有一个
dbupddate
字段,该字段指示最后一行应用的
INSERT
UPDATE
datetime

为了避免此字段具有错误的值,存在触发器(有时在之后,有时是在之后,有时是在而不是在)以确保最终值是正确的,而不是有人试图写入该字段的任何“手动”其他值

现在我正在执行一个update语句(实际上是
MERGE
),我希望有一个包含该字段的
OUTPUT
子句。正如我在书中读到的,
OUTPUT
忽略触发器

在触发器之后,是否有任何变通方法让
输出
返回值
dbupddate
has?我不想再进行另一次查询来提取信息,因为我不能保证在这些查询之间的一瞬间,另一个用户的第三次查询可能不会完全改变一切


遵循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
我猜这里的输出会忽略触发器,并返回在触发器生效后插入的默认值

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
情况下,默认值不存在,但在实际表和查询的输出中有不同的值。我既不知道如何使这些值相同,也不知道更新情况下的日期时间会发生什么。

您可以将
输出
触发器一起使用,但也必须使用
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;
Msg 334,16级,状态1,第44行 如果DML语句的目标表“dbo.Sample1”包含OUTPUT子句而不包含INTO子句,则该语句不能具有任何已启用的触发器

该错误提供了提示,请使用
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;
这适用于
插入
更新
,无论是
之后还是
而不是

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;

谢谢你的努力。不幸的是,这似乎不起作用,结果让我更加困惑。我将把我的实验结果添加到问题的末尾。@GeorgeMenoutis你不需要在
之后同时使用
触发器,而不是使用
触发器,使用其中一个,@GeorgeMenoutis?另外,您删除了默认值,因此将更改行为。哦,好的,我将把结果更改为原始的sysdatetime值。需要更多的时间来完成这项工作。。。。