對於具有標識字段的多個表,我們正在使用視圖和替代這些視圖上的觸發器來實現行級別安全方案。下面是一個簡單的例子結構:SQL Server - 在使用視圖而不是觸發器時獲取插入的記錄標識值
-- 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
如果我想插入一條記錄,並得到其身份,執行RLS INSTEAD OF觸發器之前,我用:
DECLARE @ItemId int;
INSERT INTO tblItem (Name)
VALUES ('MyName');
SELECT @ItemId = SCOPE_IDENTITY();
與觸發,SCOPE_IDENTITY( )不再有效 - 它返回NULL。我已經看到了使用OUTPUT子句獲取身份的建議,但似乎無法按照我需要的方式工作。如果我將OUTPUT子句放在視圖插入上,則不會輸入任何內容。
如果我將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');
我唯一能想到的就是使用IDENT_CURRENT()函數。由於這不適用於當前的作用域,因此同時插入併發用戶併發生混亂問題。如果整個操作被包裝在一個事務中,是否會阻止併發問題?
BEGIN TRANSACTION
DECLARE @ItemId int;
INSERT INTO tblItem (Name)
VALUES ('MyName');
SELECT @ItemId = IDENT_CURRENT('tblItem');
COMMIT TRANSACTION
有沒有人有任何建議,如何做到這一點更好?
我知道那裏的人會讀這個,並說「觸發器是邪惡的,不要使用它們!」雖然我很欣賞你的信念,但請不要提供那個「建議」。
看到我的相關問題關於CONTEXT_INFO()使用:http://stackoverflow.com/questions/1616229/contextinfo-and-convert – 2009-10-23 22:29:49
@Rob:我加了一個答案 – gbn 2009-10-24 06:56:37