2013-01-06 12 views
41
में विदेशी कुंजी वाली पंक्तियां हटाएं

मैं पंक्तियों जो एक विदेशी कुंजी समाहित मिटा देना चाहते हैं, लेकिन जब मैं कुछ इस तरह का प्रयास करें:PostgreSQL

ERROR: update or delete on table "osoby" violates foreign key constraint "kontakty_ibfk_1" on table "kontakty" DETAIL: Key (id_osoby)=(1) is still referenced from table "kontakty".

कैसे:

DELETE FROM osoby WHERE id_osoby='1' 

मैं इस बयान मिलता है क्या मैं इन पंक्तियों को हटा सकता हूं?

+1

इस पर भी जांचें [हटाए गए कैस्केड पर) (http://stackoverflow.com/questions/10356484/how-to-add-on-delete-cascade-constraints);) यह अच्छी तरह से आपकी तालिका में सेटिंग्स रखना अच्छा है हालांकि .. जब 'विदेशी कुंजी बनाना' हम 'माता-पिता को तब बच्चे' जोड़ते हैं। तो जब हम 'बच्चे को हटाएं और फिर माता-पिता' हटाते हैं;) – bonCodigo

उत्तर

42

इस स्वचालित करने के लिए हटाने के बाद आप ON DELETE CASCADE के साथ विदेशी कुंजी बाधा निर्धारित कर सकते हैं।
मैं बोली the manual of foreign key constraints:

CASCADE specifies that when a referenced row is deleted, row(s) referencing it should be automatically deleted as well.

+4

हमने 'हटाए गए कैस्केड' के साथ तालिकाओं को नहीं बनाया है। मैं टेबल की संरचना नहीं बदल सकता। क्या कोई तरीका है कि विदेशी कुंजी स्वचालित रूप से हटा दी जाती है? या हमें @juergen d – Varun

+1

@ वरुण द्वारा सुझाए गए तरीके का पालन करना होगा: यदि आप 'ओले डिलीट कैस्केड' के साथ एफके जोड़ने के लिए तालिका को 'अल्टर' नहीं कर सकते हैं, तो हाथ से (एक बार) हटाकर या ट्रिगर करके 'हटाएं' '(हर बार) शेष विकल्प हैं। –

6

इसका मतलब है कि तालिका kontakty में आपके पास osoby में पंक्ति को संदर्भित करने वाली पंक्ति है जिसे आप हटाना चाहते हैं। आपने पहले उस पंक्ति को हटा दिया है या तालिकाओं के बीच संबंध पर एक कैस्केड हटा दिया है।

Powodzenia!

21

यदि आप अभी भी किसी अन्य तालिका का संदर्भ देते हैं तो आप एक विदेशी कुंजी को हटा नहीं सकते हैं। पहले संदर्भ

delete from kontakty 
where id_osoby = 1; 

DELETE FROM osoby 
WHERE id_osoby = 1; 
12

एक एक सामान्य समाधान के रूप में इस सिफारिश नहीं करना चाहिए, लेकिन एक डेटाबेस में पंक्तियों की एक बंद विलोपन कि उत्पादन में या सक्रिय उपयोग में नहीं है के लिए, आप करने के लिए सक्षम हो सकता है प्रश्न में तालिकाओं पर अस्थायी रूप से ट्रिगर अक्षम करें।

मेरे मामले में, मैं विकास मोड में हूं और कुछ टेबल हैं जो विदेशी कुंजी के माध्यम से एक-दूसरे का संदर्भ देती हैं। इस प्रकार, उनकी सामग्री को हटाना उतना आसान नहीं है जितना कि एक पंक्ति से सभी पंक्तियों को दूसरे से पहले हटा दें। तो, मेरे लिए, यह उनकी सामग्रियों को हटाना ठीक काम इस प्रकार है:

ALTER TABLE table1 DISABLE TRIGGER ALL; 
ALTER TABLE table2 DISABLE TRIGGER ALL; 
DELETE FROM table1; 
DELETE FROM table2; 
ALTER TABLE table1 ENABLE TRIGGER ALL; 
ALTER TABLE table2 ENABLE TRIGGER ALL; 

आप को जोड़ने के लिए कहां खंड के रूप में वांछित, देखभाल के साथ निश्चित रूप से डेटाबेस की अखंडता को कम से बचने के लिए सक्षम होना चाहिए।

http://www.openscope.net/2012/08/23/subverting-foreign-key-constraints-in-postgres-or-mysql/

3

में कुछ अच्छा है, संबंधित चर्चा नहीं है यह एक समय हो गया है के बाद से यह सवाल पूछा गया था, आशा कर सकते हैं। क्योंकि आप डीबी संरचना को बदल या परिवर्तित नहीं कर सकते हैं, आप यह कर सकते हैं। postgresql docs के अनुसार।

TRUNCATE - तालिका या टेबल के सेट को खाली करें।

TRUNCATE [ TABLE ] [ ONLY ] name [ * ] [, ... ] 
    [ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ] 

विवरण

TRUNCATE जल्दी से तालिकाओं का एक सेट से सभी पंक्तियों को हटा। यह प्रत्येक तालिका पर एक अयोग्य डिलीट के समान प्रभाव है, लेकिन चूंकि यह वास्तव में तालिकाओं को स्कैन नहीं करता है, यह तेज़ है। इसके अलावा, यह बाद के वाक्यूम ऑपरेशन की आवश्यकता के बजाय तुरंत डिस्क स्थान पुनः प्राप्त करता है। यह बड़ी टेबल पर सबसे उपयोगी है।


किसी भी तालिका कि विदेशी कुंजी की कमी के माध्यम से othertable संदर्भ के लिए मेज othertable, और झरना छोटा करें:

TRUNCATE othertable CASCADE; 

ही, और भी अन्य संबद्ध अनुक्रम जनरेटर रीसेट:

TRUNCATE bigtable, fattable RESTART IDENTITY; 

किसी भी संबंधित अनुक्रम जनरेटर को छंटनी और रीसेट करें:

TRUNCATE revinfo RESTART IDENTITY CASCADE ;