मेरी पिछली पोस्ट में, "एक अग्रणी वाइल्डकार्ड के लिए अनुक्रमणिका प्राप्त करने का एक तरीका," मैंने उल्लेख किया है कि आप मेरे द्वारा सुझाए गए अंशों को बनाए रखने से निपटने के लिए ट्रिगर्स की आवश्यकता होगी। कुछ लोगों ने मुझसे यह पूछने के लिए संपर्क किया है कि क्या मैं उन ट्रिगर्स को प्रदर्शित कर सकता हूं।
पिछली पोस्ट से सरल बनाने के लिए, मान लें कि हमारे पास निम्न तालिकाएँ हैं - कंपनियों का एक सेट, और फिर एक CompanyNameFragments तालिका जो कंपनी के नाम के किसी भी विकल्प के विरुद्ध छद्म-वाइल्डकार्ड खोज की अनुमति देती है:
CREATE TABLE dbo.Companies ( CompanyID int CONSTRAINT PK_Companies PRIMARY KEY, Name nvarchar(100) NOT NULL ); GO CREATE TABLE dbo.CompanyNameFragments ( CompanyID int NOT NULL, Fragment nvarchar(100) NOT NULL ); CREATE CLUSTERED INDEX CIX_CNF ON dbo.CompanyNameFragments(Fragment, CompanyID);पर क्लस्टर इंडेक्स CIX_CNF बनाएं
टुकड़े उत्पन्न करने के लिए इस फ़ंक्शन को देखते हुए (मूल लेख से एकमात्र परिवर्तन यह है कि मैंने @input
बढ़ा दिया है 100 वर्णों का समर्थन करने के लिए):
CREATE FUNCTION dbo.CreateStringFragments( @input nvarchar(100) ) RETURNS TABLE WITH SCHEMABINDING AS RETURN ( WITH x(x) AS ( SELECT 1 UNION ALL SELECT x+1 FROM x WHERE x < (LEN(@input)) ) SELECT Fragment = SUBSTRING(@input, x, LEN(@input)) FROM x ); GO
हम एक एकल ट्रिगर बना सकते हैं जो तीनों कार्यों को संभाल सकता है:
CREATE TRIGGER dbo.Company_MaintainFragments ON dbo.Companies FOR INSERT, UPDATE, DELETE AS BEGIN SET NOCOUNT ON; DELETE f FROM dbo.CompanyNameFragments AS f INNER JOIN deleted AS d ON f.CompanyID = d.CompanyID; INSERT dbo.CompanyNameFragments(CompanyID, Fragment) SELECT i.CompanyID, fn.Fragment FROM inserted AS i CROSS APPLY dbo.CreateStringFragments(i.Name) AS fn; END GO
यह बिना किसी जाँच के काम करता है कि किस प्रकार का ऑपरेशन हुआ क्योंकि:
- एक अद्यतन या एक DELETE के लिए, DELETE होगा - एक अद्यतन के लिए, हम उन अंशों का मिलान करने की कोशिश नहीं करेंगे जो समान रहेंगे; हम बस उन सभी को उड़ा देंगे, ताकि उन्हें सामूहिक रूप से बदला जा सके। INSERT के लिए, DELETE कथन का कोई प्रभाव नहीं पड़ेगा, क्योंकि
deleted
में कोई पंक्तियाँ नहीं होंगी । - एक INSERT या एक अद्यतन के लिए, INSERT होगा। DELETE के लिए, INSERT कथन का कोई प्रभाव नहीं पड़ेगा, क्योंकि
inserted
में कोई पंक्तियाँ नहीं होंगी ।
अब, यह सुनिश्चित करने के लिए कि यह काम करता है, आइए Companies
. में कुछ बदलाव करें तालिका और फिर हमारी दो तालिकाओं का निरीक्षण करें।
-- First, let's insert two companies -- (table contents after insert shown in figure 1 below) INSERT dbo.Companies(Name) VALUES(N'Banana'), (N'Acme Corp'); -- Now, let's update company 2 to 'Orange' -- (table contents after update shown in figure 2 below): UPDATE dbo.Companies SET Name = N'Orange' WHERE CompanyID = 2; -- Finally, delete company #1 -- (table contents after delete shown in figure 3 below): DELETE dbo.Companies WHERE CompanyID = 1;
चित्र 1: प्रारंभिक तालिका सामग्री | चित्र 2: अद्यतन के बाद तालिका सामग्री | चित्र 3: हटाने के बाद तालिका सामग्री |
चेतावनी (संदर्भात्मक अखंडता लोगों के लिए)
ध्यान दें कि यदि आप इन दो तालिकाओं के बीच उचित विदेशी कुंजी सेट करते हैं, तो आपको हटाए जाने को संभालने के लिए ट्रिगर के बजाय एक का उपयोग करना होगा, अन्यथा आपको चिकन और अंडे की समस्या होगी - आप माता-पिता के *बाद* तक प्रतीक्षा नहीं कर सकते बाल पंक्तियों को हटाने के लिए पंक्ति हटा दी जाती है। तो आपको ON DELETE CASCADE
सेट करना होगा (जिसे मैं व्यक्तिगत रूप से पसंद नहीं करता), या आपके दो ट्रिगर इस तरह दिखाई देंगे (बाद के ट्रिगर को अभी भी एक अद्यतन के मामले में एक DELETE/INSERT जोड़ी करना होगा):
CREATE TRIGGER dbo.Company_DeleteFragments ON dbo.Companies INSTEAD OF DELETE AS BEGIN SET NOCOUNT ON; DELETE f FROM dbo.CompanyNameFragments AS f INNER JOIN deleted AS d ON f.CompanyID = d.CompanyID; DELETE c FROM dbo.Companies AS c INNER JOIN deleted AS d ON c.CompanyID = d.CompanyID; END GO CREATE TRIGGER dbo.Company_MaintainFragments ON dbo.Companies FOR INSERT, UPDATE AS BEGIN SET NOCOUNT ON; DELETE f FROM dbo.CompanyNameFragments AS f INNER JOIN deleted AS d ON f.CompanyID = d.CompanyID; INSERT dbo.CompanyNameFragments(CompanyID, Fragment) SELECT i.CompanyID, fn.Fragment FROM inserted AS i CROSS APPLY dbo.CreateStringFragments(i.Name) AS fn; END GO
सारांश
इस पोस्ट का उद्देश्य यह दिखाना था कि ट्रिगर सेट करना कितना आसान है जो तलाशने योग्य . को बनाए रखेगा वाइल्डकार्ड खोजों को बेहतर बनाने के लिए स्ट्रिंग के टुकड़े, कम से कम मध्यम आकार के स्ट्रिंग्स के लिए। अब, मुझे अभी भी पता है कि इस तरह का विचार एक निराला विचार के रूप में सामने आता है, लेकिन मैं इसके बारे में बात करता रहता हूं क्योंकि मुझे विश्वास है कि वहाँ अच्छे उपयोग के मामले हैं।
अपनी अगली पोस्ट में, मैं दिखाऊंगा कि इस पसंद के प्रभाव को कैसे देखा जाए:आप क्वेरी समय पर प्रदर्शन बचत के खिलाफ टुकड़ों को बनाए रखने की संसाधन लागत की तुलना करने के लिए आसानी से प्रतिनिधि वर्कलोड सेट कर सकते हैं। मैं अलग-अलग स्ट्रिंग लंबाई के साथ-साथ अलग-अलग वर्कलोड बैलेंस (ज्यादातर पढ़ा बनाम अधिकतर लिखता हूं) को देखूंगा और मीठे धब्बे और खतरे के क्षेत्रों को खोजने का प्रयास करूंगा।