2009-10-23 11 views
5

Kimlik alanları olan birkaç tablo için, bu görünümlerdeki Görünümler ve Bunun yerine Tetikleyicileri kullanarak bir Satır Düzeyi Güvenlik şeması uyguluyoruz. Ben bir kayıt eklemek ve yerine tetikleyici Of RLS uygulamadan önce, kendi kimliğini almak istiyorsanızSQL Server - Bir Görünümün Tetikleyicinin Yerini Kullanırken Eklenen Kayıt Kimliği Değerini Alın

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

, kullandığım: tetik, SCOPE_IDENTITY ile

DECLARE @ItemId int; 

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

SELECT @ItemId = SCOPE_IDENTITY(); 

(İşte basitleştirilmiş bir örnek yapıdır) artık çalışmıyor - NULL döndürür. Kimliği geri almak için OUTPUT yan tümcesini kullanma önerileri gördüm, ancak ihtiyacım olan şekilde çalışmasını sağlayamıyorum. OUTPUT yan tümcesini görünüm ekine koyarsam, buna hiçbir şey girilmez.

Ben INSERT ekstresinde tetikleyici ÇIKIŞ maddesini koyarsanız
-- Nothing is added to @ItemIds 
DECLARE @ItemIds TABLE (ItemId int); 

INSERT INTO vwItem (Name) 
OUTPUT INSERTED.ItemId INTO @ItemIds 
VALUES ('MyName'); 

, tetik tablo (SQL Management Studio de görüntüleyebilir) döndürür. Onu arama kodunda yakalayamıyorum; ya bu çağrıdaki bir OUTPUT yan tümcesi kullanılarak veya SELECT * FROM() kullanılarak.

-- 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'); 

Düşünebildiğim tek şey IDENT_CURRENT() işlevini kullanmaktır. Bu, mevcut kapsamda çalışmadığından, aynı anda ekleyerek eşzamanlı kullanıcıların bir sorunu vardır. Tüm işlem bir işlemde sarılmışsa, eş zamanlılık sorununu engeller mi?

BEGIN TRANSACTION 

DECLARE @ItemId int; 

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

SELECT @ItemId = IDENT_CURRENT('tblItem'); 

COMMIT TRANSACTION 

Bunu nasıl yapacaklarına dair herhangi bir önerisi var mı?

Bunu okuyan ve "Tetikleyiciler EVIL, onları kullanma!" Diyen insanlar tanıyorum. Kanaatinizi takdir ederken, lütfen bu "öneriyi" sunmayın.

cevap

1

İstemcideki CONTEXT_INFO() tarafından okunacak şekilde tetikleyiciden SET CONTEXT_INFO deneyebilirsiniz.

Bilgileri tetikleyiciye aktarmanın başka bir yolu olarak kullanıyoruz, ancak ters yönde çalışacağız.

+1

CONTEXT_INFO() kullanımıyla ilgili ilgili soruma bakın: http://stackoverflow.com/questions/1616229/contextinfo-and-convert –

+0

@Rob: Bu – gbn

1

Bu durumda denediniz @@ kimlik? Scope_Identity() ve identity_current() öğelerini değil, @@ kimliğini belirtmiştiniz.

+0

İyi düşünceye bir yanıt ekledim. Olağan kapsam belirleme "problemi" bu durumda yardımcı olabilir. – gbn

+0

@@ IDENTITY, IDENT_CURRENT() öğesinden nasıl daha iyi olur? Anladığım kadarıyla, ikisi de çağrı kodunun kapsamı ile sınırlı olmamakla birlikte, @@ IDENTITY nerede olursa olsun eklenen son kimlik değeridir. Dolayısıyla, bir denetim tablosuna bir kayıt ekleyen tabloda bir denetim tetiği varsa, @ IDENTITY bu satırın kimliğini döndürebilir (doğru anlıyorsam). Bu yüzden IDENT_CURRENT() öğesinin daha iyi olduğunu düşündüm çünkü en azından "kapsamı" belirli bir tabloyla sınırlı tutuyordu. – CuppM

+0

@CuppM: @@ IDENTITY, oturum başına değil, oturum başına. IDENT_CURRENT(), ne – gbn