Giải thích tốt về hành vi xếp tầng (TRÊN XÓA / CẬP NHẬT)


98

Tôi không thiết kế lược đồ hàng ngày, nhưng khi tôi làm, tôi cố gắng thiết lập cập nhật / xóa tầng một cách chính xác để quản trị dễ dàng hơn. Tôi hiểu cách thức hoạt động của tầng, nhưng tôi không bao giờ có thể nhớ bảng nào là bảng nào.

Ví dụ: nếu tôi có hai bảng - ParentChild- có khóa ngoại trên Childtham chiếu đó Parentvà có ON DELETE CASCADE, bản ghi nào kích hoạt một tầng và bản ghi nào bị xóa bởi tầng? Dự đoán đầu tiên của tôi sẽ là các Childhồ sơ bị xóa khi Parenthồ sơ bị xóa, vì Childhồ sơ phụ thuộc vào Parenthồ sơ, nhưng ON DELETElà mơ hồ; nó có thể có nghĩa là xóa Parentbản ghi khi Childbản ghi bị xóa, hoặc nó có thể có nghĩa là xóa Childbản ghi khi bản ghi Parentbị xóa. Vậy đó là cái gì?

Tôi muốn cú pháp là ON PARENT DELETE, CASCADE, ON FOREIGN DELETE, CASCADEhoặc một cái gì đó tương tự để loại bỏ sự mơ hồ. Có ai có bất kỳ ghi nhớ để nhớ điều này?

Câu trả lời:


138

Nếu bạn thích ParentChildđiều khoản và bạn cảm thấy họ rất dễ được nhớ đến, bạn có thể muốn bản dịch của ON DELETE CASCADEđểLeave No Orphans!

Điều đó có nghĩa là khi một Parenthàng bị xóa (bị giết), không có hàng mồ côi nào tồn tại trong Childbảng. Tất cả trẻ em của hàng cha mẹ cũng bị giết (bị xóa). Nếu bất kỳ đứa trẻ nào trong số chúng có cháu (trong một bảng khác thông qua khóa ngoại khác) và đã được ON DELETE CASCADExác định, chúng cũng sẽ bị giết (và tất cả các hậu duệ, miễn là có hiệu ứng tầng được xác định.)

Các FOREIGN KEYràng buộc cũng có thể được mô tả là Allow No Orphans!(ở vị trí đầu tiên). Không Childbao giờ được phép (bằng văn bản) trong bảng con nếu nó không có Parent(một hàng trong bảng cha).

Để thống nhất, ON DELETE RESTRICTcó thể được dịch thành (ít khó chịu hơn) You Can't Kill Parents!Chỉ có thể giết hàng không có con (bị xóa).


3
Tôi cảm thấy một cái gì đó vẫn còn thiếu trong tương tự. Một đứa trẻ có thể có nhiều hơn một cha mẹ? Trong trường hợp này sẽ giết một phụ huynh làm cho đứa trẻ trở thành một đứa trẻ mồ côi?
Jus12

7
@ Jus12 Không, các ràng buộc khóa ngoại chỉ hoạt động với 1 cha mẹ. Nó không phải là một sự tương tự tốt về khía cạnh này.
ypercubeᵀᴹ

1
@ypercube: Điều này không được phép? Order(custID, itemID, orderID)trong đó custIDđề cập đến một khóa chính trong Customersbảng và itemIDđề cập đến một khóa chính trong Itemsbảng. Không Ordercó hai cha mẹ?
Jus12

4
@ Jus12 Điều đó được cho phép tất nhiên nhưng nó sẽ là 2 ràng buộc khóa ngoại. Sau đó, mọi đứa trẻ (đặt hàng) sẽ có cha mẹ (khách hàng) và cha mẹ (vật phẩm). Các hành vi của 2 FK có thể khác nhau mặc dù. (Vì vậy, ví dụ, nó có thể là giết chết khách hàng sẽ giết tất cả họ (đơn đặt hàng) con nhưng giết chết mục sẽ không giết đơn đặt hàng của họ.)
ypercubeᵀᴹ

1
Sự tương tự cha mẹ vẫn có thể hoạt động nếu chúng ta không nói "mồ côi". Nếu có hai tham chiếu đến hai cha mẹ riêng biệt trong một mục nhập con, điều này vẫn có thể được xem là con của một cặp vợ chồng ly dị. Hạn chế: "Tôi sẽ không để bạn giết mẹ tôi" Cascade: "Nếu bạn giết bố tôi, tôi cũng sẽ chết"
Christopher McGowan

31

Ví dụ: nếu tôi có hai bảng - Cha mẹ và Con - nơi hồ sơ Con được sở hữu bởi hồ sơ Cha mẹ, bảng nào cần BẬT XÓA BỊ XÓA?

TRÊN XÓA CASCADE là một mệnh đề tùy chọn trong khai báo khóa ngoài. Vì vậy, nó đi với khai báo khóa nước ngoài. (Có nghĩa là, trong bảng "con".)

... nó có thể có nghĩa là xóa bản ghi gốc khi bản ghi con bị xóa hoặc có thể có nghĩa là xóa bản ghi con khi phần cha mẹ bị xóa. Vậy đó là cái gì?

Một cách để diễn giải một khai báo khóa ngoại là "Tất cả các giá trị hợp lệ cho cột này đến từ 'that_column' trong 'that_table'." Khi bạn xóa một hàng trong bảng "con", không ai quan tâm. Nó không ảnh hưởng đến tính toàn vẹn dữ liệu.

Khi bạn xóa một hàng khỏi bảng "cha mẹ" - từ "that_table" - bạn xóa một giá trị hợp lệ khỏi các giá trị có thể cho bảng "con". Để duy trì tính toàn vẹn dữ liệu, bạn phải làm một cái gì đó với bảng "con". Xóa tầng là một điều bạn có thể làm.


2

Thông số SQL: 2011

Có năm tùy chọn cho ON DELETE, và ON UPDATEcó thể áp dụng cho FOREIGN KEY. Chúng được gọi <referential actions>, trực tiếp từ thông số SQL: 2011

  • ON DELETE CASCADE: nếu một hàng của bảng tham chiếu bị xóa, thì tất cả các hàng khớp trong bảng tham chiếu sẽ bị xóa.
  • ON DELETE SET NULL: nếu một hàng của bảng được tham chiếu bị xóa, thì tất cả các cột tham chiếu trong tất cả các hàng khớp của bảng tham chiếu sẽ được đặt thành null.
  • ON DELETE SET DEFAULT: nếu một hàng của bảng được tham chiếu bị xóa, thì tất cả các cột tham chiếu trong tất cả các hàng khớp của bảng tham chiếu sẽ được đặt thành giá trị mặc định của cột.
  • ON DELETE RESTRICT: cấm xóa một hàng của bảng được tham chiếu nếu hàng đó có bất kỳ hàng khớp nào trong bảng tham chiếu.
  • ON DELETE NO ACTION (mặc định) : không có hành động xóa tham chiếu; ràng buộc tham chiếu chỉ xác định kiểm tra ràng buộc.

Khóa ngoại thiết lập mối quan hệ phụ thuộc. Việc <referential action>xác định những gì xảy ra khi mối quan hệ bị hòa tan.

Ví dụ / Ẩn dụ / Giải thích

Trong ví dụ này, chúng tôi sẽ chấp nhận mô hình chung của xã hội và nền kinh tế: nơi mọi businesscông ty đều duy trì mối quan hệ bourgeoisiethông qua a fatcat_owner.

CREATE TABLE bourgeoisie(
  fatcat_owner varchar(100) PRIMARY KEY
);
INSERT INTO bourgeoisie(fatcat_owner) VALUES
  ( 'Koch Brothers' );

CREATE TABLE business (
  name         varchar(100),
  fatcat_owner varchar(100) REFERENCES bourgeoisie
);
INSERT INTO business(name, fatcat_owner)
  VALUES ('Georgia-Pacific', 'Koch Brothers');

Nếu tất cả các businesses bị ảnh hưởng trực tiếp bourgeoisiebởi cách của họ fatcat_ownerthì bạn sẽ làm gì sau cuộc cách mạng của công nhân khi bạn thanh trừng những người fatcat_ownerđó và có một xã hội không có giai cấp?

-- Viva la revolución 
BEGIN;
  DELETE FROM bourgeoisie;
END;

Bạn có một vài lựa chọn ở đây,

  • Dừng cuộc cách mạng. Theo cách nói của SQL , RESTRICT. Một số người tin rằng đây là điều xấu xa hơn, nhưng họ thường sai.
  • Cho phép nó tiếp tục. Nếu vậy khi cuộc cách mạng xảy ra, SQL cung cấp cho bạn bốn tùy chọn,

    • SET NULL-- để trống. Ai biết được, có thể chủ nghĩa tư bản được khôi phục bourgeoisievà các đầu sỏ chính trị lấp đầy fatcat_owners. Lưu ý quan trọng, cột phải NULLABLE(không NOT NULL) hoặc điều này không bao giờ có thể xảy ra.
    • SET DEFAULT- có lẽ bạn đã có một DEFAULTxử lý này? A DEFAULTcó thể gọi một chức năng. Có thể lược đồ của bạn đã sẵn sàng cho cuộc cách mạng.
    • CASCADE- không có kiểm soát thiệt hại. Nếu bourgeoisieđi, thì cũng vậy business. Nếu một doanh nghiệp phải có một fatcat_pig, thì đôi khi nó có ý nghĩa hơn để mất dữ liệu hơn là không có một doanh nghiệp trong một businessbảng.
    • NO ACTION- đây thực chất là một phương pháp trì hoãn kiểm tra, trong MySQL không khác gì RESTRICT, nhưng trong PostgreQuery, bạn có thể làm được

      -- Not a real revolution.
      -- requires constraint be DEFERRABLE INITIALLY DEFERRED
      BEGIN;
        SET CONSTRAINTS ALL DEFERRED;
        DELETE FROM bourgeoisie;
        INSERT INTO bourgeoisie VALUES ( 'Putin' );
        UPDATE business SET fatcat_pig = 'Putin';
      END;
      

      Trong một hệ thống như vậy, ràng buộc chỉ được xác nhận trước khi giao dịch được thực hiện. Điều này có thể dẫn đến việc dừng cuộc cách mạng, nhưng bạn có thể phục hồi trong giao dịch - đối với một mức độ "phục hồi" nào đó.


Liệu referencedbảng có nghĩa là bảng cha và referencingbảng nghĩa bảng con?
sg552

@ sg552 Vâng, bạn đã hiểu đúng.
informatik01

0

Một ghi nhớ đơn giản sẽ là

TRÊN XÓA cha mẹ CASCADE [bằng cách xóa] tại đây

Điều đó cho bạn biết những xóa nào (xóa của cha mẹ) được xếp tầng, trong đó câu lệnh ON DELETE CASCADE đi (trên con) và những gì bị xóa (con).


-3

tốt, có lẽ chúng ta có thể hợp lý hóa cú pháp. Hãy lấy một ví dụ về Python:

class Parent(self):
    # define parent's fields

class Child(self):    
    # define child's fields
    parent_pk_is_childs_foreign_key = models.ForeignKey(Parent, on_delete=models.CASCADE)

những gì dòng này nói là on_delete của Parent (được vô tình đề cập trong tuyên bố), xin vui lòng xếp tầng xóa vào đứa trẻ. Đó là lý do tại sao câu lệnh CASCADE được xác định ở cấp độ con, nó đánh dấu những đứa trẻ cần được xóa

Ví dụ nếu bạn có một lớp học khác

class GrownUpChild(self):    
        # define grown up child's fields
        parent_pk_is_childs_foreign_key = models.ForeignKey(Parent, on_delete=models.DO_NOTHING)

cấu trúc này sẽ cho thấy rõ những đứa trẻ nào cần được loại bỏ (Đứa trẻ) và đứa trẻ nào sẽ ở lại (GrownUpChild) mặc dù mồ côi

[Chỉnh sửa: Với bối cảnh thảo luận, cụ thể là trong các trường hợp on_delete = model.CASCADE, v.v.] trên thực tế, đó thường là hành vi mong muốn để lại con cái của cha mẹ bị xóa, vì lý do kiểm toán và báo cáo, cũng như phục hồi tình cờ xóa. [tất nhiên phần mềm cấp doanh nghiệp sẽ được xây dựng xung quanh hành vi đó và sẽ gắn cờ các bản ghi bị xóa là đã xóa = 1 thay vì thực sự xóa chúng và cũng sẽ không đưa chúng vào bất kỳ truy vấn nào cho giao diện người dùng, trừ một số báo cáo được thiết kế đặc biệt. Ngoài ra, nó sẽ có chức năng xóa các bản ghi == 1 đã xóa khỏi cơ sở dữ liệu, thường sẽ được quản trị viên UI thực thi, thường tránh mọi liên quan từ phía quản trị viên cơ sở dữ liệu.]


1
'Trên thực tế, việc để con cái của cha mẹ bị xóa thường là một hành vi mong muốn, vì lý do kiểm toán và báo cáo, cũng như khôi phục việc xóa do vô tình' - điều đó sẽ là thảm họa trong cơ sở dữ liệu (lành mạnh).
dezso

@dezso cảm ơn bạn đã đóng góp. Tuy nhiên, nhiều hệ thống CRM cấp doanh nghiệp thực hiện chính xác điều đó.
George Mogilevsky

TBH mà không làm cho nó hợp lý hơn. Tôi đã từng có một nhiệm vụ để sửa shit do cách tiếp cận như vậy - không có niềm vui, ngoại trừ tiền lương.
dezso

bạn có vẻ như một quản trị viên cơ sở dữ liệu hiểu biết :) Tôi hoàn toàn có thể nghe quan điểm của bạn. Phần mềm tôi đã đề cập ở trên, thực sự có chức năng xóa những người đã xóa = 1 theo cách thủ công để tùy thuộc vào quản trị viên của ứng dụng thực hiện cuộc gọi này. Thông thường quản trị viên cơ sở dữ liệu thậm chí không tham gia vào việc duy trì khía cạnh này. Và bên cạnh đó, lớp cơ sở dữ liệu của toàn bộ phần mềm được xây dựng xung quanh khái niệm này, vì vậy nó luôn kiểm tra cờ đã bị xóa trong các hoạt động thô sơ
George Mogilevsky

Vâng, đó là một mô hình đã biết và lành mạnh - nhưng sau đó bạn có thể nên thay đổi từ ngữ ở trên để phản ánh điều này.
dezso
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.