簡體   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