खोज…


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" में सभी प्रविष्टियों को हटा देगा ... (अब कोई गैर-डेल्टा अपडेट नहीं)



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow