Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Ràng buộc khóa ngoại:Khi nào sử dụng BẬT CẬP NHẬT và BẬT XÓA

Đừng ngần ngại đặt các ràng buộc trên cơ sở dữ liệu. Bạn sẽ chắc chắn có một cơ sở dữ liệu nhất quán và đó là một trong những lý do chính đáng để sử dụng cơ sở dữ liệu. Đặc biệt nếu bạn có nhiều ứng dụng yêu cầu nó (hoặc chỉ một ứng dụng nhưng có chế độ trực tiếp và chế độ hàng loạt sử dụng các nguồn khác nhau).

Với MySQL, bạn không có các ràng buộc nâng cao như trong postgreSQL nhưng ít nhất các ràng buộc khóa ngoại khá nâng cao.

Chúng tôi sẽ lấy một ví dụ, một bảng công ty với một bảng người dùng chứa những người từ công ty luận án

CREATE TABLE COMPANY (
     company_id INT NOT NULL,
     company_name VARCHAR(50),
     PRIMARY KEY (company_id)
) ENGINE=INNODB;

CREATE TABLE USER (
     user_id INT, 
     user_name VARCHAR(50), 
     company_id INT,
     INDEX company_id_idx (company_id),
     FOREIGN KEY (company_id) REFERENCES COMPANY (company_id) ON...
) ENGINE=INNODB;

Hãy xem CẬP NHẬT BẬT mệnh đề:

  • HẠN CHẾ CẬP NHẬT : mặc định :nếu bạn cố gắng cập nhật company_id trong bảng COMPANY, công cụ sẽ từ chối hoạt động nếu một NGƯỜI DÙNG có ít nhất liên kết trên công ty này.
  • BẬT CẬP NHẬT KHÔNG CÓ HÀNH ĐỘNG :giống như HẠN CHẾ.
  • BẬT CẬP NHẬT CASCADE : cái tốt nhất thường :nếu bạn cập nhật company_id trong một hàng của bảng COMPANY, công cụ sẽ cập nhật nó tương ứng trên tất cả các hàng USER tham chiếu đến COMPANY này (nhưng không có trình kích hoạt nào được kích hoạt trên bảng USER, cảnh báo). Công cụ sẽ theo dõi những thay đổi cho bạn, điều đó thật tốt.
  • BẬT CẬP NHẬT CÀI ĐẶT ĐẦY ĐỦ :nếu bạn cập nhật company_id trong một hàng của bảng COMPANY, công cụ sẽ đặt các USER có liên quan company_id thành NULL (sẽ có sẵn trong trường USER company_id). Tôi không thể thấy bất kỳ điều thú vị nào để làm với điều đó trên một bản cập nhật, nhưng có thể tôi đã nhầm.

Và bây giờ trên BẬT XÓA bên:

  • HẠN CHẾ XÓA : mặc định :nếu bạn cố gắng xóa id company_id trong bảng COMPANY, công cụ sẽ từ chối hoạt động nếu một NGƯỜI DÙNG có ít nhất liên kết trên công ty này, có thể cứu mạng bạn.
  • BẬT XÓA KHÔNG CÓ HÀNH ĐỘNG :giống như RESTRICT
  • BẬT XÓA CASCADE : nguy hiểm :nếu bạn xóa một hàng công ty trong bảng COMPANY, công cụ cũng sẽ xóa những NGƯỜI DÙNG có liên quan. Điều này nguy hiểm nhưng có thể được sử dụng để tự động dọn dẹp trên các bảng phụ (vì vậy nó có thể là thứ bạn muốn, nhưng chắc chắn không phải đối với ví dụ COMPANY <-> USER)
  • BẬT XÓA THIẾT LẬP KHÔNG ĐỦ : một số ít :nếu bạn xóa một hàng COMPANY, các USER có liên quan sẽ tự động có mối quan hệ với NULL. Nếu Null là giá trị của bạn đối với người dùng không có công ty thì đây có thể là một hành vi tốt, chẳng hạn như có thể bạn cần giữ người dùng trong ứng dụng của mình, với tư cách là tác giả của một số nội dung, nhưng việc xóa công ty không phải là vấn đề đối với bạn.

thường mặc định của tôi là: HẠN CHẾ XÓA KHI CẬP NHẬT CASCADE . với một số ON DELETE CASCADE cho bảng theo dõi (nhật ký - không phải tất cả nhật ký--, những thứ tương tự) và ON DELETE SET NULL khi bảng chính là 'thuộc tính đơn giản' cho bảng chứa khóa ngoại, như bảng JOB cho bảng USER.

Chỉnh sửa

Đã lâu rồi tôi không viết như vậy. Bây giờ tôi nghĩ tôi nên thêm một cảnh báo quan trọng. MySQL có một hạn chế lớn được ghi nhận với các tầng. Các tầng không kích hoạt trình kích hoạt . Vì vậy, nếu bạn đã quá tin tưởng vào công cụ đó để sử dụng trình kích hoạt, bạn nên tránh các ràng buộc về tầng.

==> Xem bên dưới lần chỉnh sửa cuối cùng, mọi thứ đang diễn ra trên miền này

Và tôi không nghĩ điều này sẽ được khắc phục một ngày nào đó. Các ràng buộc khóa ngoại được quản lý bởi bộ lưu trữ InnoDb và các Trigger được quản lý bởi MySQL SQL engine. Cả hai đều được tách ra. Innodb là bộ lưu trữ duy nhất có quản lý ràng buộc, có thể một ngày nào đó họ sẽ thêm trình kích hoạt trực tiếp vào công cụ lưu trữ, có thể không.

Nhưng tôi có ý kiến ​​riêng về yếu tố nào bạn nên chọn giữa việc triển khai trình kích hoạt kém và hỗ trợ ràng buộc khóa ngoại rất hữu ích. Và khi bạn đã quen với tính nhất quán của cơ sở dữ liệu, bạn sẽ thích PostgreSQL.

12/2017-Đang cập nhật Chỉnh sửa này về MySQL:

như được nêu bởi @IstiaqueAhmed trong các nhận xét, tình hình đã thay đổi về chủ đề này. Vì vậy, hãy theo liên kết và kiểm tra tình hình cập nhật thực tế (có thể thay đổi lại trong tương lai).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. cột json so với nhiều cột

  2. Chọn truy vấn bằng IN () và không có bất kỳ phân loại nào

  3. mysql WHERE TRONG chuỗi / tên người dùng mảng

  4. com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:Lỗi liên kết truyền thông

  5. Sử dụng Docker, tôi gặp lỗi:SQLSTATE [HY000] [2002] Không có tệp hoặc thư mục nào như vậy