2017-01-03 9 views
5

मैं एक उत्प्रेरक है कि इस तरह एक विधानसभा कॉल बनाया है तर्क पारित करने के लिए:कैसे एक बाहरी (SQLCLR) SQL सर्वर ट्रिगर

CREATE TRIGGER Testrigger ON STATION 
FOR INSERT 
AS EXTERNAL NAME assemblytest.[WriteTimeInfile.Program].Testrigger 

कि विधानसभा में नेट कोड है कि कुछ इस तरह है:

namespace WriteTimeInfile 
{ 
    public class Program 
    { 
     [SqlTrigger(Name = @"Testrigger", Target = "[dbo].[STATION]", Event = "FOR INSERT, UPDATE, DELETE")] 
     public static void Testrigger() 
     { 
      File.AppendAllText(@"C:\Users\Vivien\date.txt", 
      DateTime.Now.ToString() + Environment.NewLine); 
     } 
    } 
} 

मैं एक तर्क, बनाया पंक्ति या इस तरह अद्यतन पंक्ति कुछ के रूप में, पारित करने में सक्षम होना चाहते हैं:

CREATE TRIGGER Testrigger ON STATION 
AFTER INSERT 
AS 
EXTERNAL NAME assemblytest.[WriteTimeInfile.Program].Testrigger (STATION.ID) 

मुझे स्टैक ओवरफ्लो पर 7 साल पुराना topic मिला जो बताता है कि सीएलआर असेंबली को तर्क देने का कोई तरीका नहीं है।
मैं पूछ रहा हूं कि यह हाल ही में SQL सर्वर संस्करणों में संभव है या नहीं।

क्या आपको पता है कि कोई रास्ता है और यदि हां, तो कृपया इसे कैसे करें?

+0

आपके पास हमेशा SQLCLR ट्रिगर के अंदर से INSERTED और हटाए गए तालिकाओं तक पहुंच थी, [जैसा कि डॉक्यूमेंटेशन के इस पुराने संस्करण में दिखाया गया है) (https://msdn.microsoft.com/en-us/library/938d9dz2 (v = vs.90) .aspx)। आपको ट्रिगर में किसी भी तर्क को पारित करने की आवश्यकता नहीं है, जैसे कि आपको सामान्य ट्रिगर –

+0

* पर किसी भी तर्क को पारित करने की आवश्यकता नहीं है * आप * ट्रिगर्स को पैरामीटर क्यों पास करना चाहते हैं? किस तरह के पैरामीटर? आप इसके बजाय संग्रहीत प्रक्रिया का उपयोग क्यों नहीं करते? यदि आप परिवर्तन पहचान के साथ किसी प्रकार की ईटीएल कार्यक्षमता को कार्यान्वित करना चाहते हैं, तो आप चाबियाँ खोजने और संशोधित पंक्तियों के प्रकार बदलने के लिए चेंज ट्रैकिंग (सीडीसी नहीं) का उपयोग कर सकते हैं और उन्हें –

उत्तर

3

नहीं, आप सीधे एसक्यूएलसीएलआर ट्रिगर्स को तर्क नहीं दे सकते हैं। हालांकि, आप मूल्यों परोक्ष रूप से कुछ तरीकों से (एक ही नियमित T-SQL ट्रिगर के साथ के रूप में) पारित कर सकते हैं:

  1. स्थानीय अस्थायी तालिका
  2. SET CONTEXT_INFO/CONTEXT_INFO
  3. एसक्यूएल सर्वर 2016 या नए पर: sp_set_session_context/SESSION_CONTEXT

सभी मामलों में आप एक निर्गम SqlParameter के साथ एक SqlCommand क्रियान्वित नेट कोड में मूल्य को खींचने के लिए से मूल्यों को प्राप्त होगा। (कृपया उपयोग के अंत में नोट देखें)।

लेकिन अगर आप inserted और/या deleted तालिकाओं के मान चाहते हैं, तो वे तर्क या पैरामीटर नहीं होंगे। कनेक्शन स्ट्रिंग के लिए Context Connection = true का उपयोग करके SqlCommand का उपयोग करके SELECT और SqlDataReader का उपयोग कर रहे हैं। Sample CLR Trigger अनुभाग में, आप CLR Triggers के लिए एमएसडीएन पृष्ठ में इसका एक उदाहरण देख सकते हैं।


कि DML ऑपरेशन का हिस्सा नहीं हैं ट्रिगर करने के लिए गुजर मूल्यों के बारे में ध्यान दें:

हालांकि यह नहीं है बहुत का एक टुकड़ा पारित करने के लिए, वहाँ निश्चित रूप से कर रहे हैं वैध उपयोग के मामलों करने के लिए आम मुख्य संदर्भ से जानकारी घटनाओं की श्रृंखला में एक या अधिक ट्रिगर्स तक। मेरे द्वारा सामने आने वाले दो सबसे आम मामले हैं: 1) एप-आधारित लॉगिन या उपयोगकर्ता आईडी (एसक्यूएल सर्वर का हिस्सा नहीं) में गुजरने वाले पंक्तियों के लिए एक ऑडिट ट्रिगर में गुज़रना (क्योंकि उस जानकारी को DELETE में संशोधित बाई कॉलम में जोड़ा नहीं जा सकता है ऑपरेशन), और 2) अस्थायी रूप से एक शर्त के आधार पर एक ट्रिगर अक्षम करना। और हाँ, यह संभव है और यह काम करता है। डीबीए पर मेरा निम्नलिखित जवाब देखें।StackExchange:

+0

ट्रिगर्स का उपयोग करने की कोशिश कर रहे हैं जैसे कि वे संग्रहीत प्रक्रियाओं का अर्थ है कि वे पहली जगह –

+0

@ पानागियोटिस कानावोस में ट्रिगर नहीं होना चाहिए यदि यह ट्रिगर्स का उपयोग करने की कोशिश करने का मामला था जैसे कि वे संग्रहीत प्रक्रियाएं थीं तो मैं आपके साथ सहमत हूं :-)। लेकिन निश्चित रूप से ऐसे मामले हैं जो ट्रिगर्स का उपयोग कर रहे हैं क्योंकि उनका उपयोग अभी भी किया जाना चाहिए, इस अवसर पर, इस आवश्यकता में भाग लें। –

+1

@srutzky धन्यवाद, आप मेरी आधिकारिक समस्या हल कर रहे हैं –

1

डाला जाता है और हटा छद्म तालिकाओं के रूप में दस्तावेज की this 9+ years old version में दिखाया गया है, एक SQLCLR ट्रिगर अंदर प्रत्यक्ष क्वेरी किए जाने के लिए उपलब्ध हमेशा थे। आप हमेशा उनसे पूछ सकते हैं, उदाहरण के लिए:

using (SqlConnection conn = new SqlConnection("context connection=true")) 
{ 
    conn.Open(); 
    SqlCommand sqlComm = new SqlCommand(); 
    SqlPipe sqlP = SqlContext.Pipe; 

    sqlComm.Connection = conn; 
    sqlComm.CommandText = "SELECT UserName from INSERTED"; 

    userName.Value = sqlComm.ExecuteScalar().ToString(); 

    if (IsEMailAddress(userName.Value.ToString())) 
    { 
     sqlComm.Parameters.Add(userName); 
     sqlComm.CommandText = "INSERT UsersAudit(UserName) VALUES(@username)"; 
     sqlP.Send(sqlComm.CommandText); 
     sqlP.ExecuteAndSend(sqlComm); 
    } 
} 

नवीनतम नमूने समान हैं।

आपको उन्हें पैरामीटर के रूप में पास करने की आवश्यकता नहीं है, जैसे कि आपको सामान्य ट्रिगर्स के पैरामीटर के रूप में पास करने की आवश्यकता नहीं है। पूछताछ के लिए टेबल हमेशा उपलब्ध हैं।

मुझे संदेह है कि इन तालिकाओं को संदर्भ वस्तु पर संग्रहीत नहीं किया गया है क्योंकि उन्हें SQL सर्वर के बफर (सीपीयू और मेमोरी को बर्बाद करने) से कॉपी करने की आवश्यकता होगी। एक अन्य कारण यह है कि एक संग्रह प्रभावी ढंग से पूछताछ नहीं की जा सकती है। आपको या तो LINQ (और भी सीपीयू का उपयोग करके) का उपयोग करना होगा या पूरी सामग्री (मेमोरी और सीपीयू कचरा) पर बस फिर से उपयोग करना होगा। मेमोरी कचरा बड़ी समस्या होगी, क्योंकि इस मेमोरी का उपयोग अधिक डेटा और इंडेक्स को बफर करने के लिए किया जा सकता है, इस प्रकार पहुंच को तेज़ी से बढ़ाया जा सकता है।

मुझे संदेह है कि आप जिस प्रश्न से जुड़े थे, वही सवाल पूछना चाहते थे, लेकिन ओपी ने माना कि छद्म-टेबल को पैरामीटर के रूप में पारित किया जाना था। तो उन्होंने वास्तविक मुद्दे के बजाय पैरामीटर के बारे में पूछा।

+0

धन्यवाद, यह जानना अच्छा है, लेकिन मैं अद्यतन पंक्ति या किसी भी परम से भीम को पारित करने में सक्षम होना चाहूंगा, –

+0

आप किसी के साथ ऐसा नहीं कर सकते वैसे भी ट्रिगर करें क्योंकि यह समझ में नहीं आता है। ट्रिगर सर्वर द्वारा निष्पादित किए जाते हैं ताकि आप उनके बाहर के मूल्यों में हेरफेर नहीं कर सकें। ** पंक्तियों ** (बहुवचन) के लिए, ये पहले से ही उपलब्ध हैं। * बहुवचन * महत्वपूर्ण हिस्सा है। वे उस अंतर्निहित या हटाए गए तालिका में एक या दस लाख पंक्तियां हो सकती हैं। वाक्यविन्यास बदलता है, लेकिन तालिकाओं तक पहुंचने के तरीके एक ही –

+0

@ विवियनिपो और पैनागियोटिस बना रहता है: हालांकि यह करने के लिए सामान्य नहीं है, हालांकि मुख्य संदर्भ से एक या अधिक जानकारी के टुकड़े को पास करने के लिए निश्चित रूप से वैध उपयोग के मामले हैं घटनाओं की श्रृंखला में ट्रिगर्स। मेरे द्वारा सामने आने वाले दो सबसे आम मामले हैं: 1) हटाए गए पंक्तियों के लिए ऐप-आधारित लॉगिन या उपयोगकर्ता आईडी (SQL सर्वर का हिस्सा नहीं) में गुजरना (क्योंकि उस जानकारी को 'हटाए गए' कॉलम में 'संशोधित' कॉलम में जोड़ा नहीं जा सकता है ऑपरेशन), और 2) अस्थायी रूप से एक शर्त के आधार पर एक ट्रिगर अक्षम करना। और हाँ, जैसा कि मैंने अपने जवाब में दिखाया है, यह संभव है और यह काम करता है :-)। –