SQL Server - 使用视图而不是触发器时获取插入的记录标识值

Cup*_*ppM 5 sql t-sql sql-server triggers identity

对于具有标识字段的多个表,我们在这些视图上使用视图和替代触发器实现行级安全性方案.这是一个简化的示例结构:

-- Table
CREATE TABLE tblItem (
    ItemId int identity(1,1) primary key,
    Name varchar(20)
)
go

-- View
CREATE VIEW vwItem 
AS
    SELECT *
    FROM tblItem
    -- RLS Filtering Condition
go

-- Instead Of Insert Trigger
CREATE TRIGGER IO_vwItem_Insert ON vwItem
INSTEAD OF INSERT
AS BEGIN
    -- RLS Security Checks on inserted Table

    -- Insert Records Into Table
    INSERT INTO tblItem (Name)
    SELECT Name
    FROM inserted;
END
go
Run Code Online (Sandbox Code Playgroud)

如果我想插入记录并获取其身份,在实现RLS而不是触发器之前,我使用了:

DECLARE @ItemId int;

INSERT INTO tblItem (Name)
VALUES ('MyName');

SELECT @ItemId = SCOPE_IDENTITY();
Run Code Online (Sandbox Code Playgroud)

使用触发器,SCOPE_IDENTITY()不再起作用 - 它返回NULL.我已经看到了使用OUTPUT子句来获取身份的建议,但我似乎无法让它以我需要的方式工作.如果我在视图插入上放置OUTPUT子句,则不会输入任何内容.

-- Nothing is added to @ItemIds
DECLARE @ItemIds TABLE (ItemId int);

INSERT INTO vwItem (Name)
OUTPUT INSERTED.ItemId INTO @ItemIds
VALUES ('MyName');
Run Code Online (Sandbox Code Playgroud)

如果我将OUTPUT子句放在INSERT语句的触发器中,则触发器返回表(我可以从SQL Management Studio中查看它).我似乎无法在调用代码中捕获它; 通过在该调用上使用OUTPUT子句或使用SELECT*FROM().

-- Modified Instead Of Insert Trigger w/ Output
CREATE TRIGGER IO_vwItem_Insert ON vwItem
INSTEAD OF INSERT
AS BEGIN
    -- RLS Security Checks on inserted Table

    -- Insert Records Into Table
    INSERT INTO tblItem (Name)
    OUTPUT INSERTED.ItemId
    SELECT Name
    FROM inserted;
END
go

-- Calling Code
INSERT INTO vwItem (Name)
VALUES ('MyName');
Run Code Online (Sandbox Code Playgroud)

我唯一能想到的就是使用IDENT_CURRENT()函数.由于这不在当前范围内运行,因此存在并发用户同时插入并弄乱它的问题.如果整个操作都包含在事务中,那会阻止并发问题吗?

BEGIN TRANSACTION

DECLARE @ItemId int;

INSERT INTO tblItem (Name)
VALUES ('MyName');

SELECT @ItemId = IDENT_CURRENT('tblItem');

COMMIT TRANSACTION
Run Code Online (Sandbox Code Playgroud)

有没有人对如何做得更好有任何建议?

我知道有人会读到这个并说"触发器是邪恶的,不要使用它们!" 虽然我感谢您的信念,但请不要提供"建议".

gbn*_*gbn 1

您可以尝试SET CONTEXT_INFO从触发器中读取CONTEXT_INFO()客户端。

我们使用另一种方式将信息传递到触发器中,但会反向工作。