2013-01-06 12 views
41

Tôi muốn xóa hàng có chứa một chìa khóa nước ngoài, nhưng khi tôi thử một cái gì đó như thế này:Xóa hàng với khóa ngoại trong PostgreSQL

DELETE FROM osoby WHERE id_osoby='1' 

tôi nhận tuyên bố này:

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".

thế nào thế nào tôi có thể xóa các hàng này?

+1

Kiểm tra về điều này cũng như [trên xóa thác] (http://stackoverflow.com/questions/10356484/how-to-add-on-delete-cascade-constraints);) Tốt để có các cài đặt này trong bảng của bạn Mặc dù .. Khi 'tạo các khóa ngoại ', chúng ta sẽ bổ sung thêm" cha mẹ "và con". Vì vậy, khi xóa chúng tôi 'xóa con và sau đó cha mẹ';) – bonCodigo

Trả lời

42

Để tự động này, bạn có thể định nghĩa các ràng buộc khoá ngoại với ON DELETE CASCADE.
tôi trích dẫn 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

Chúng tôi không có bảng được tạo với ON' DELETE CASCADE'. Tôi không thể thay đổi cấu trúc của bảng. Có cách nào để các phím nước ngoài bị xóa tự động không? hoặc chúng ta phải làm theo cách được đề xuất bởi @juergen d – Varun

+1

@Varun: Nếu bạn không thể 'ALTER' bảng để thêm một FK với' ON DELETE CASCADE', sau đó xóa bằng tay (một lần) hoặc bằng cách kích hoạt 'TRƯỚC KHI DELETE '(mọi thời gian) là các tùy chọn còn lại. –

6

Điều này có nghĩa là trong bảng kontakty bạn có một hàng tham chiếu hàng trong số osoby bạn muốn xóa. Bạn phải xóa hàng đó trước hoặc đặt xóa tầng trên mối quan hệ giữa các bảng.

Powodzenia!

21

Bạn không thể xóa khóa ngoại nếu nó vẫn tham chiếu đến một bảng khác. Đầu tiên xóa các tài liệu tham khảo

delete from kontakty 
where id_osoby = 1; 

DELETE FROM osoby 
WHERE id_osoby = 1; 
12

Người ta không nên đề nghị này như một giải pháp chung, nhưng đối với một lần xóa hàng trong một cơ sở dữ liệu mà không phải là trong sản xuất hoặc sử dụng hoạt động, bạn có thể tạm thời vô hiệu hóa trình kích hoạt trên các bảng được đề cập.

Trong trường hợp của tôi, tôi đang ở chế độ phát triển và có một vài bảng tham chiếu lẫn nhau thông qua khóa ngoại. Do đó, việc xóa nội dung của chúng không đơn giản như việc xóa tất cả các hàng khỏi một bảng trước bảng kia. Vì vậy, đối với tôi, nó làm việc tốt để xóa nội dung của họ như sau:

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; 

Bạn sẽ có thể thêm mệnh đề WHERE như mong muốn, tất nhiên với việc chăm sóc để tránh hủy hoại sự toàn vẹn của cơ sở dữ liệu.

Có một số tốt, thảo luận liên quan tại http://www.openscope.net/2012/08/23/subverting-foreign-key-constraints-in-postgres-or-mysql/

3

Nó được một lúc kể từ khi câu hỏi này được hỏi, hy vọng có thể giúp đỡ. Bởi vì bạn không thể thay đổi hoặc thay đổi cấu trúc db, bạn có thể làm điều này. theo postgresql docs.

TRUNCATE - để trống một bảng hoặc bộ bảng.

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

Mô tả

TRUNCATE nhanh chóng loại bỏ tất cả các hàng từ một tập hợp các bảng. Nó có tác dụng tương tự như DELETE không đủ tiêu chuẩn trên mỗi bảng, nhưng vì nó không thực sự quét các bảng nhanh hơn. Hơn nữa, nó lấy lại không gian đĩa ngay lập tức, thay vì yêu cầu một hoạt động VACUUM tiếp theo. Điều này hữu ích nhất trên các bảng lớn.


Truncate bảng othertable, và thác cho bất kỳ bảng tham chiếu othertable qua trở ngại foreign-key:

TRUNCATE othertable CASCADE; 

Cùng, và cũng có thể thiết lập lại bất kỳ máy phát điện chuỗi liên kết:

TRUNCATE bigtable, fattable RESTART IDENTITY; 

Cắt ngắn và đặt lại bất kỳ trình tạo trình tự liên quan nào:

TRUNCATE revinfo RESTART IDENTITY CASCADE ;