2009-10-23 8 views
5

पहचान फ़ील्ड वाले कई तालिकाओं के लिए, दृश्य दृश्य पहचान योजना का उपयोग करते समय, हम दृश्यों का उपयोग करके और उन विचारों पर ट्रिगर्स के बजाय एक पंक्ति स्तर सुरक्षा योजना लागू कर रहे हैं।एसक्यूएल सर्वर - ट्रिगर

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

अगर मैं एक रिकॉर्ड सम्मिलित और इसके बजाय ट्रिगर के आरएलएस लागू करने से पहले अपनी पहचान पाने के लिए, चाहता हूँ, मैं प्रयोग किया है::

DECLARE @ItemId int; 

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

SELECT @ItemId = SCOPE_IDENTITY(); 
ट्रिगर, SCOPE_IDENTITY साथ

(यहाँ एक सरल उदाहरण संरचना है) अब काम नहीं करता है - यह शून्य देता है। मैंने पहचान प्राप्त करने के लिए OUTPUT क्लॉज का उपयोग करने के लिए सुझाव देखे हैं, लेकिन मुझे ऐसा करने के लिए प्रतीत नहीं होता है जिस तरह से मुझे इसकी आवश्यकता है। अगर मैं दृश्य सम्मिलन पर आउटपुट खंड डालता हूं, तो इसमें कुछ भी दर्ज नहीं किया जाता है।

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

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

अगर मैं सम्मिलित बयान पर ट्रिगर में आउटपुट खंड में कहें, ट्रिगर तालिका (मैं एसक्यूएल प्रबंधन स्टूडियो से इसे देख सकते हैं) देता है। मैं इसे कॉलिंग कोड में कैप्चर नहीं कर सकता; या तो उस कॉल पर एक OUTPUT क्लॉज का उपयोग करके या चयन * 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 

क्या किसी को यह बेहतर तरीके से करने के बारे में कोई सुझाव है?

मैं वहां लोगों को जानता हूं जो इसे पढ़ेंगे और कहेंगे "ट्रिगर्स EVIL हैं, उनका उपयोग न करें!" जबकि मैं आपके विश्वासों की सराहना करता हूं, कृपया उस "सुझाव" की पेशकश न करें।

उत्तर

1

आप क्लाइंट में CONTEXT_INFO() द्वारा पढ़े जाने वाले ट्रिगर से SET CONTEXT_INFO को आजमा सकते हैं।

हम ट्रिगर में जानकारी पास करने के लिए इसे अन्य तरीके का उपयोग करते हैं लेकिन विपरीत में काम करेंगे।

+1

CONTEXT_INFO() उपयोग के बारे में मेरा संबंधित प्रश्न देखें: http://stackoverflow.com/questions/1616229/contextinfo-and-convert –

+0

@Rob: मैंने इस – gbn

1

क्या आपने इस मामले में @@ पहचान की कोशिश की है? आपने scope_Identity() और identity_current() दोनों का उल्लेख किया है लेकिन @@ पहचान नहीं।

+0

अच्छी सोच का उत्तर जोड़ा। इस मामले में सामान्य स्कोपिंग "समस्या" एक मदद हो सकती है। – gbn

+0

IDENT_CURRENT() से @@ पहचान बेहतर कैसे होगी? जो मैं समझता हूं, उससे न तो कॉलिंग कोड के दायरे तक सीमित है, @@ पहचान अंतिम पहचान मूल्य है जहां कोई फर्क नहीं पड़ता है। इसलिए यदि मेरे पास टेबल पर ऑडिट ट्रिगर है जो ऑडिट तालिका में रिकॉर्ड डालता है, तो @@ पहचान उस पंक्ति की पहचान वापस कर सकती है (यदि मैं सही ढंग से समझता हूं)। यही कारण है कि मुझे लगता है कि IDENT_CURRENT() बेहतर था क्योंकि यह कम से कम "स्कोप" को विशिष्ट तालिका तक सीमित कर देता था। – CuppM

+0

@CuppM: @@ पहचान प्रति सत्र है, प्रति गुंजाइश नहीं। IDENT_CURRENT() न तो है और किसी भी सत्र/स्कोप – gbn

संबंधित मुद्दे