SQL
कैस्केडिंग हटाएं
खोज…
DELETE CASCADE पर
मान लें कि आपके पास एक एप्लिकेशन है जो कमरों का प्रशासन करता है।
आगे मान लें कि आपका एप्लिकेशन प्रति ग्राहक आधार (किरायेदार) पर चल रहा है।
आपके पास कई ग्राहक हैं।
इसलिए आपके डेटाबेस में क्लाइंट्स के लिए एक टेबल और कमरों के लिए एक टेबल होगी।
अब, हर क्लाइंट के पास N कमरे हैं।
इसका मतलब यह होना चाहिए कि आपके पास अपने टेबल पर एक विदेशी कुंजी है, जो क्लाइंट टेबल को संदर्भित करता है।
ALTER TABLE dbo.T_Room WITH CHECK ADD CONSTRAINT FK_T_Room_T_Client FOREIGN KEY(RM_CLI_ID)
REFERENCES dbo.T_Client (CLI_ID)
GO
क्लाइंट को किसी अन्य सॉफ़्टवेयर में ले जाने पर, आपको अपने सॉफ़्टवेयर में उसका डेटा हटाना होगा। लेकिन अगर आप
DELETE FROM T_Client WHERE CLI_ID = x
तब आपको एक विदेशी कुंजी का उल्लंघन मिलेगा, क्योंकि जब वह अभी भी कमरे में है तो आप ग्राहक को नहीं हटा सकते।
अब आप अपने आवेदन में कोड लिखेंगे जो ग्राहक को हटाने से पहले ग्राहक के कमरे को हटा देगा। आगे यह मान लें कि भविष्य में, आपके डेटाबेस में कई और विदेशी कुंजी निर्भरताएं जोड़ी जाएंगी, क्योंकि आपके आवेदन की कार्यक्षमता का विस्तार होता है। भयानक। अपने डेटाबेस में हर संशोधन के लिए, आपको अपने एप्लिकेशन के कोड को N स्थानों में बदलना होगा। संभवतः आपको अन्य अनुप्रयोगों में भी कोड को अनुकूलित करना होगा (जैसे अन्य प्रणालियों के लिए इंटरफेस)।
अपने कोड में इसे करने से बेहतर उपाय है।
आप बस अपनी विदेशी कुंजी ON DELETE CASCADE
जोड़ सकते हैं।
ALTER TABLE dbo.T_Room -- WITH CHECK -- SQL-Server can specify WITH CHECK/WITH NOCHECK
ADD CONSTRAINT FK_T_Room_T_Client FOREIGN KEY(RM_CLI_ID)
REFERENCES dbo.T_Client (CLI_ID)
ON DELETE CASCADE
अब आप कह सकते हैं
DELETE FROM T_Client WHERE CLI_ID = x
और ग्राहक को हटाए जाने पर कमरे स्वचालित रूप से हटा दिए जाते हैं।
समस्या हल हुई - कोई एप्लिकेशन कोड परिवर्तन नहीं।
सावधानी का एक शब्द: Microsoft SQL-Server में, यह काम नहीं करेगा यदि आपके पास एक तालिका है जो स्वयं को संदर्भित करती है। तो अगर आप एक पुनरावर्ती पेड़ संरचना पर एक नष्ट झरना को परिभाषित करने की कोशिश करते हैं, तो इस तरह:
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_T_FMS_Navigation_T_FMS_Navigation]') AND parent_object_id = OBJECT_ID(N'[dbo].[T_FMS_Navigation]'))
ALTER TABLE [dbo].[T_FMS_Navigation] WITH CHECK ADD CONSTRAINT [FK_T_FMS_Navigation_T_FMS_Navigation] FOREIGN KEY([NA_NA_UID])
REFERENCES [dbo].[T_FMS_Navigation] ([NA_UID])
ON DELETE CASCADE
GO
IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_T_FMS_Navigation_T_FMS_Navigation]') AND parent_object_id = OBJECT_ID(N'[dbo].[T_FMS_Navigation]'))
ALTER TABLE [dbo].[T_FMS_Navigation] CHECK CONSTRAINT [FK_T_FMS_Navigation_T_FMS_Navigation]
GO
यह काम नहीं करेगा, क्योंकि Microsoft-SQL- सर्वर आपको एक पुनरावर्ती ट्री संरचना पर ON DELETE CASCADE
साथ एक विदेशी कुंजी सेट करने की अनुमति नहीं देता है। इसका एक कारण यह है कि पेड़ संभवतः चक्रीय है, और इससे संभवतः गतिरोध पैदा होगा।
दूसरी ओर PostgreSQL यह कर सकता है;
आवश्यकता यह है कि पेड़ गैर-चक्रीय है।
यदि पेड़ चक्रीय है, तो आपको एक रनटाइम त्रुटि मिलेगी।
उस स्थिति में, आपको बस डिलीट फंक्शन को लागू करना होगा।
चेतावनी:
इसका मतलब है कि आप ग्राहक तालिका को अब आसानी से हटा नहीं सकते हैं और फिर से डाल सकते हैं, क्योंकि यदि आप ऐसा करते हैं, तो यह "T_Room" में सभी प्रविष्टियों को हटा देगा ... (अब कोई गैर-डेल्टा अपडेट नहीं)