2009-02-09 15 views
9

में स्वयं-संदर्भ बाधाएं क्या यह सच है कि एमएस एसक्यूएल ऑन डिलीट कैस्केड विकल्प के साथ स्वयं-संदर्भ बाधाओं को प्रतिबंधित करता है? मेरे पास अभिभावक-बाल संबंध वाला एक टेबल है, PARENT_ID कॉलम आईडी के लिए विदेशी कुंजी है। DELETE CASCADE विकल्प चालू साथ यह बनाने में त्रुटिएमएस एसक्यूएल

"अन्य विदेशी कुंजी की कमी विदेशी कुंजी बाधा परिचय चक्र या एक से अधिक झरना पथ हो सकती है। पर निर्दिष्ट कोई कार्रवाई नहीं की अद्यतन से कोई भी कार्रवाई या हटा सकते हैं या संशोधित कारण बनता है। "

मुझे विश्वास नहीं है कि मुझे रिकर्सिव मोड में इस पदानुक्रम को हटाना है। ट्रिगर्स को छोड़कर कोई समस्या है?

उत्तर

9

यह मामला है कि आप स्वयं-संदर्भ बाधाओं वाले तालिका पर डिलीट कैस्केड पर सेट अप नहीं कर सकते हैं। चक्रीय तर्क समस्याओं की संभावना है, इसलिए यह इसकी अनुमति नहीं देगा।

एक अच्छा लेख here है - हालांकि यह SQL के 9 के बजाय संस्करण 8 के लिए है - हालांकि वही नियम लागू होते हैं।

+0

PostgreSQL यह समर्थन करता है। अब अगर एक और प्रविष्टि जिसे हटाया नहीं जाना है, तो एक उपखंड को हटाया जाना है, यह एक त्रुटि जारी करेगा, और हटाए गए ऑपरेशन को वापस ले जाया जाएगा। अन्यथा, यह पूरी तरह से काम करेगा। वास्तविक मुद्दा यह है कि क्या आपके माता-पिता के संबंध गैर-चक्रीय निर्देशित ग्राफ हैं या नहीं। चूंकि अधिकांश आत्म-संदर्भ पदानुक्रमों को लागू करते हैं, और पदानुक्रमों को गैर-चक्रीय ग्राफों को निर्देशित किया जाना चाहिए, अधिकांश मामलों में PostgreSQL के कार्यवाही का कार्य अधिक गंभीर होना चाहिए। अन्य सभी मामलों में, आप अभी भी उस कार्यक्षमता को मैन्युअल रूप से कार्यान्वित कर सकते हैं, इसलिए कुछ भी नहीं खो गया है। –

0
CREATE TRIGGER MyTable_OnDelete ON MyTable 
INSTEAD OF DELETE 
AS 
BEGIN 

    SET NOCOUNT ON; 

    DELETE FROM mt 
    FROM deleted AS D 
    JOIN MyTable AS mt 
    ON  d.Id = mt.ParentId 

    DELETE FROM mt 
    FROM deleted AS D 
    JOIN MyTable AS mt 
    ON  d.Id = mt.Id 

END 
+0

क्षमा करें, लेकिन एक मामले में यदि 'MyTable' किसी अन्य तालिका के साथ संबंध में है (' हटाए गए कैस्केड पर ... ') आप' 'DELETE' DESTTE 'ट्रिगर को परिभाषित नहीं कर सकते हैं ... – Bellash

4

मैं सिर्फ another question जहां इस सवाल डुप्लीकेट के रूप में ही था जवाब दे दिया। मुझे लगता है कि यहां मेरा उत्तर भी देना उचित है:

यह संभव नहीं है। आप एक INSTEAD OF TRIGGER

create table locations 
(
    id int identity(1, 1), 
    name varchar(255) not null, 
    parent_id int, 

    constraint pk__locations 
     primary key clustered (id) 

) 
GO 

INSERT INTO locations(name,parent_id) VALUES 
('world',null) 
,('Europe',1) 
,('Asia',1) 
,('France',2) 
,('Paris',4) 
,('Lyon',4); 
GO 

--This ट्रिगर के साथ इस का समाधान एक पुनरावर्ती CTE उपयोग करने वाले सभी आईडी आप हटा रहे हैं निम्नलिखित सभी आईडी प्राप्त करने के लिए कर सकते हैं। ये आईडी हटा दी गई हैं।

CREATE TRIGGER dbo.DeleteCascadeLocations ON locations 
INSTEAD OF DELETE 
AS 
BEGIN 
    WITH recCTE AS 
    (
     SELECT id,parent_id 
     FROM deleted 

     UNION ALL 

     SELECT nxt.id,nxt.parent_id 
     FROM recCTE AS prv 
     INNER JOIN locations AS nxt ON nxt.parent_id=prv.id 
    ) 
    DELETE FROM locations WHERE id IN(SELECT id FROM recCTE); 
END 
GO 

- इसे यहां देखें, विभिन्न आईडी के साथ प्रयास करें। आप (वास्तविक डेटा के साथ Carefull!) WHERE id IN(4,3) भी कोशिश कर सकते हैं ...

SELECT * FROM locations; 

DELETE FROM locations WHERE id=4; 

SELECT * FROM locations 
GO 

--Clean-अप

if exists(select 1 from INFORMATION_SCHEMA.TABLES where TABLE_NAME='locations') 
---DROP TABLE locations; 
+0

मेरे पास एक सारणी है जो स्वयं को संदर्भित करती है तीन स्तर गहरे, इस के साथ व्यापक परीक्षण किया और यह पूरी तरह से काम करता है। आपको बहुत - बहुत धन्यवाद! – vaindil

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