2010-03-03 17 views
5

मैं एक एसक्यूएल तालिका के रूप में नीचे परिभाषित किया गया है:समग्र प्राथमिक कुंजी और विदेशी कुंजी बाधा त्रुटि

CREATE TABLE [TestComposite] ( 
    ID int, 
    SiteUrl nvarchar(255), 
    Name nvarchar(max) NOT NULL, 
    ParentID int NULL, 
    PRIMARY KEY (ID, SiteUrl) 
); 

आइटम और फ़ोल्डरों, एक ही तालिका के अंदर जमा हो जाती है, तो एक आइटम एक फ़ोल्डर के अंदर है, ParentID स्तंभ है फ़ोल्डर की आईडी। और जब मैं फ़ोल्डर हटाता हूं तो मैं CASCADE आइटम/फ़ोल्डर को हटाने में सक्षम होना चाहता हूं।

एक उदाहरण अधिक स्पष्ट हो सकता है:

INSERT INTO [TestComposite] VALUES (1, 'site1', 'Item1', NULL) 
INSERT INTO [TestComposite] VALUES (2, 'site1', 'Item2', NULL) 
INSERT INTO [TestComposite] VALUES (3, 'site1', 'Folder1', NULL) 
INSERT INTO [TestComposite] VALUES (4, 'site1', 'Folder1.Item1', 3) 
INSERT INTO [TestComposite] VALUES (5, 'site1', 'Folder1.Item2', 3) 
INSERT INTO [TestComposite] VALUES (6, 'site1', 'Folder1.Folder1', 3) 
INSERT INTO [TestComposite] VALUES (7, 'site1', 'Folder1.Folder1.Item1', 6) 
etc... 

तो अगर मैं आइटम 3 (एक फ़ोल्डर), मैं चाहता हूँ आइटम/फ़ोल्डर 4, 5, 6 और 7 भी हटाए जाने के लिए हटा दें। विदेशी कुंजी बाधा का परिचय
तालिका 'TestComposite' चालू 'fk_parentid' चक्र या एक से अधिक झरना रास्तों का कारण हो सकता:

मैं एक बाधा के समान जोड़ने की कोशिश की:

ALTER TABLE [TestComposite] 
ADD CONSTRAINT fk_parentid 
FOREIGN KEY (ParentID, SiteUrl) 
REFERENCES [TestComposite] (ID, SiteUrl) ON DELETE CASCADE; 

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

मैंने पेरेंटसाइट यूआरएल नामक दूसरा साइट यूआरएल कॉलम जोड़ने का भी प्रयास किया, यदि समस्या यह थी कि एक कॉलम एक ही एफके/पीके का हिस्सा नहीं होगा, लेकिन मेरे पास एक ही त्रुटि संदेश है।

क्या मैं कुछ गलत कर रहा हूं?

धन्यवाद,

उत्तर

5

एक ON DELETE NO ACTION बाधा बना सकते हैं और इस का उपयोग सभी रिकॉर्ड और अपने बच्चों को नष्ट करने के लिए:

WITH q AS 
     (
     SELECT id, SiteURL 
     FROM TestComposite 
     WHERE id = 3 
       AND SiteURL = 'site1' 
     UNION ALL 
     SELECT tc.id, tc.SiteURL 
     FROM q 
     JOIN TestComposite tc 
     ON  tc.ParentID = q.Id 
       AND tc.SiteURL = q.SiteURL 
     ) 
DELETE 
FROM TestComposite 
WHERE EXISTS 
     (
     SELECT id, SiteURL 
     INTERSECT 
     SELECT * 
     FROM q 
     ) 
+0

मैं गलत हो सकता हूं क्योंकि मैंने अभी तक इसका परीक्षण नहीं किया है, लेकिन मुझे नहीं लगता कि यह मेरे मामले में आइटम 7 को हटा देगा, क्योंकि यह पदानुक्रम के दूसरे स्तर पर है? –

+0

'ओमाआर': हाँ यह' 7' भी हटा देगा। यह एक रिकर्सिव 'सीटीई' है। – Quassnoi

+0

धन्यवाद, यह बहुत अच्छा काम करता है। मुझे रिकर्सिव सीटीई के बारे में पता नहीं था। और ऐसा लगता है कि यह SQL Server 2005 और SQL Server 2008 दोनों पर काम करता है। –

0

मुझे लगता है कि आप क्या करना ParentId नामक कॉलम जोड़कर प्राप्त किया जा सकता है, और फिर प्राथमिक कुंजी के साथ विदेशी कुंजी के रूप में यह घोषणा करना चाहता हूँ। इस तरह से समस्या हल हो जाएगी और आप अभी भी वह सब कुछ कर सकते हैं जो आप चाहते हैं

+0

क्षमा करें, मुझे समझ नहीं आता कि तुम मुझे क्या करना चाहते हैं क्या ?! –

0

समस्या यह है कि आप रिकर्सिव कैस्केड की संभावना बनाते हैं - जब प्रत्येक कैस्केड द्वारा हटाए गए बाद में किसी भी संख्या में हटाए जा सकते हैं। एमएस एसक्यूएल इसका समर्थन नहीं करता है। मैन्युअल रूप से उन्हें अपने कोड में हटाने की कोशिश करें। बीटीडब्ल्यू मैं कैस्केड deletes की सिफारिश नहीं है।

http://support.microsoft.com/kb/321843

+0

जैसा कि मैंने अरडमैन से कहा था, अगर मेरे पास एक समग्र प्राथमिक कुंजी नहीं है, तो केवल आईडी कहें, मैं समस्या के बिना एक रिकर्सिव विदेशी कुंजी बनाने में सक्षम हूं। टेबल myTable बनाएं (आईडी int प्राथमिक कुंजी, नाम nvarchar (अधिकतम), अभिभावक int); वैकल्पिक तालिका myTable कंसस्ट्रेंट fk_parentID विदेशी कुंजी (अभिभावक) CASCADE DELETE पर myTable (आईडी) संदर्भित करता है; नहीं? –

+0

नहीं आप नहीं कर सकते! मैंने अभी कोशिश की यह समग्र कुंजी के बारे में नहीं है या नहीं, यह है कि आप कैस्केड पर एक रिकर्सन बना सकते हैं और एसक्यूएल सर्वर खुद को नहीं करना चाहता – Andrey

+0

यह अजीब बात है, मैं कसम खाता हूं कि मैंने पहले ही इसे बनाया है ... मैं इसे फिर से जांचूंगा :) –

1

आप एसक्यूएल सर्वर 2008 है, तो इस काम के लिए HierarchyID प्रकार से उपयोग करें।

+0

धन्यवाद, मैं आपका स्वागत है ओएमआर –

+0

। –

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