2011-11-24 20 views
23

में विदेशी कुंजी के साथ डेटा हटाएं मैं SQL सर्वर तालिका (पैरेंट) में डेटा को हटाने जा रहा हूं जिसमें किसी अन्य तालिका (बच्चे) के साथ संबंध है।
मैंने मूल हटाई गई क्वेरी की कोशिश की। लेकिन यह काम नहीं कर रहा है (और मुझे पता है कि यह नहीं होगा)।SQL सर्वर तालिका

DELETE FROM table WHERE ... 

यह त्रुटि

DELETE कथन संदर्भ बाधा के साथ विरोध हुआ निम्नलिखित लौटे ...

मैं मेज स्कीमा रखने की जरूरत है। मुझे पता है कि मुझे सिर्फ प्रश्न में कुछ शब्द जोड़ने की ज़रूरत है, मैंने पहले कभी ऐसा किया है, लेकिन मैं इसे याद नहीं कर सका।

उत्तर

12

यदि आप स्वचालित होने की इच्छा चाहते हैं, तो आपको अपनी स्कीमा बदलनी होगी ताकि विदेशी कुंजी बाधा ON DELETE CASCADE हो।

अधिक जानकारी के लिए, MSDN page on Cascading Referential Integrity Constraints देखें।

ईटीए (पोस्टर से स्पष्टीकरण के बाद): यदि आप स्कीमा को अपडेट नहीं कर सकते हैं, तो आपको पहले प्रभावित बाल रिकॉर्ड मैन्युअल रूप से हटा देना होगा।

+0

आह। मैं अपनी पोस्ट में उस हिस्से को बताने से चूक गया, मुझे इसे स्कीमा को बदले बिना काम करना है। यह सही है? – Andha

+1

नहीं, कुछ जादू प्रश्न विकल्प या जो कुछ भी संभव नहीं है। आपको मैन्युअल रूप से हटाना होगा। –

28

अक्षम कर सकते हैं और इससे पहले कि और हटाने के बाद विदेशी कुंजी की कमी को पुन: सक्षम:

alter table MyOtherTable nocheck constraint all 
delete from MyTable 
alter table MyOtherTable check constraint all 
+5

यदि आप अक्षम करते हैं तो बाधाओं को फिर से सक्षम करें, तो टूटी हुई 'विदेशी कुंजी' संदर्भों के कारण पुन: सक्षम विफल नहीं होगा? –

+0

नहीं, जब आप किसी फ़ील्ड में नए मान लिखते हैं तो यह केवल बाधा की जांच करता है - जब आप चेक वापस डालते हैं तो यह पूरी तालिका को पुन: स्कैन नहीं करता है। –

+3

ठीक है। इसका मतलब है कि बाल तालिका में मौजूद सभी डेटा वहां रहेगा। मैं 2k पंक्तियों को हटाने वाला हूं, और मुझे लगता है कि अगर मैं बाल तालिका में डेटा रखता हूं तो यह भारी होगा। मुझे लगता है कि मैं इसे मैन्युअल रूप से कर दूंगा। जवाब दोस्तों के लिए वैसे भी Thx। आप +1 के लायक हैं :) – Andha

2

तो, आप अन्य संदर्भ के लिए विरोध हुआ टेबल या UPDATE उनके FOREIGN KEY स्तंभ के लिए अधिक तार्किक से DELETE संबंधित पंक्तियों की जरूरत PRIMARY KEY पैरेंट टेबल से है।

इसके अलावा, आप इस लेख Don’t Delete – Just Don’t

26

आप मैन्युअल रूप से बच्चों को हटाने की आवश्यकता को पढ़ने के लिए चाहते हो सकता है। <condition> दोनों प्रश्नों के लिए समान है।

DELETE FROM child 
FROM cTable AS child 
INNER JOIN table AS parent ON child.ParentId = parent.ParentId 
WHERE <condition>; 

DELETE FROM parent 
FROM table AS parent 
WHERE <condition>; 
+0

क्या इन दो डिलीट्स को इस तरह से जोड़ा जा सकता है कि मुझे केवल भाग एक बार लिखना है? –

+1

मुझे विश्वास नहीं है तो @ थॉमस टेम्पेलमैन। यदि आप केवल एक बार शर्त लिखना चाहते हैं, तो आपको प्रत्येक तालिका के साथ मैन्युअल रूप से निपटने के बजाय कैस्केड डिलीट चालू करना होगा। एलिस्टेयर माव का जवाब यहां इस विकल्प का भी संदर्भ देता है। –

2

आप तो शामिल होने के बस मूल तालिका से डेटा हटाएं उल्लेख करते हुए बच्चे को मेज से डेटा को हटाने के लिए है parent_child के रिश्ते, पहले होने तालिका से डेटा को हटाने के लिए, उदाहरण के नीचे दिया गया है

DELETE ChildTable 
FROM ChildTable inner join ChildTable on PParentTable.ID=ChildTable.ParentTableID 
WHERE <WHERE CONDITION> 


DELETE ParentTable 
WHERE <WHERE CONDITION> 
+0

यदि आप हटाए गए कैस्केडिंग नहीं कर रहे हैं तो यह सबसे अच्छा जवाब है। कर्सर बहुत ही निष्पादित करते हैं और हटाने के लिए बाधाओं को हटाते हैं अन्य टेबलों में अनाथ पंक्तियां छोड़ सकते हैं। – Corv1nus

5
यहाँ

आप अपने "बाल" तालिका के लिए विदेशी कुंजी जोड़ रहे हैं

ALTER TABLE child 
ADD FOREIGN KEY (P_Id) 
REFERENCES parent(P_Id) 
ON DELETE CASCADE 
ON UPDATE CASCADE; 

उसके बाद यदि आप इस

DELETE FROM parent WHERE ..... 

की तरह "पिता" मेज पर एक हटाएँ क्वेरी बनाने के बाद से बच्चे को हटाना कैस्केड साथ माता-पिता के लिए एक संदर्भ है, "चाइल्ड" पंक्तियों भी होगा हटा दिया जाना चाहिए! "पैरेंट" के साथ।

1

उपयोगी स्क्रिप्ट जो आपको एक डेटाबेस के सभी तालिकाओं में सभी डेटा हटा सकते हैं साथ आप databse नाम टीटी की जगह:

declare @tablename nvarchar(100) 
declare c1 cursor for 
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_CATALOG='tt' AND TABLE_TYPE='BASE TABLE' 

open c1 
fetch next from c1 into @tablename 

while @@FETCH_STATUS = 0 
    begin 
    print @t1 
     exec('alter table ' + @tablename + ' nocheck constraint all') 
     exec('delete from ' + @tablename) 
     exec ('alter table ' + @tablename + ' check constraint all') 
     fetch next from c1 into @tablename 
    end 
close c1 
DEALLOCATE c1