2009-10-23 43 views
5

對於具有標識字段的多個表,我們正在使用視圖和替代這些視圖上的觸發器來實現行級別安全方案。下面是一個簡單的例子結構: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 

有沒有人有任何建議,如何做到這一點更好?

我知道那裏的人會讀這個,並說「觸發器是邪惡的,不要使用它們!」雖然我很欣賞你的信念,但請不要提供那個「建議」。

回答

1

您可以嘗試從觸發器中的SET CONTEXT_INFO在客戶端被CONTEXT_INFO()讀取。

我們用另一種方式將信息傳遞給觸發器,但會反向工作。

+1

看到我的相關問題關於CONTEXT_INFO()使用:http://stackoverflow.com/questions/1616229/contextinfo-and-convert – 2009-10-23 22:29:49

+0

@Rob:我加了一個答案 – gbn 2009-10-24 06:56:37

1

你有沒有在這種情況下試過@@身份?你提到了scope_Identity()和identity_current(),但不是@@ identity。

+0

好想法。在這種情況下,通常的範圍「問題」可能是一個幫助。 – gbn 2009-10-23 19:12:42

+0

@@ IDENTITY將如何比IDENT_CURRENT()更好?根據我的理解,雖然不限於調用代碼的範圍,但無論身處何處,@@ IDENTITY都是插入的最後一個標識值。因此,如果我在將記錄插入審計表的表上有審計觸發器,@@ IDENTITY可以返回該行的標識(如果我理解正確的話)。這就是爲什麼我認爲IDENT_CURRENT()更好,因爲它至少限制了特定表的「範圍」。 – CuppM 2009-10-23 19:24:12

+0

@CuppM:@@ IDENTITY是每個會話,而不是每個範圍。 IDENT_CURRENT()既不是,也可以通過任何會話/範圍 – gbn 2009-10-23 19:27:02

相關問題