Tại sao các khóa ngoại tổng hợp cần một ràng buộc duy nhất riêng biệt?


10

Đây là một bảng đơn giản nơi các bản ghi có thể tham chiếu các bản ghi cha trong cùng một bảng:

CREATE TABLE foo (
    id         SERIAL  PRIMARY KEY,
    parent_id  INT     NULL,
    num        INT     NOT NULL,
    txt        TEXT    NULL,
    FOREIGN KEY (parent_id) REFERENCES foo(id)
);

Với yêu cầu bổ sung rằng một trong các giá trị trường khác ( num) phải giống hệt nhau giữa các bản ghi cha và con, tôi nghĩ rằng một khóa ngoại tổng hợp sẽ thực hiện thủ thuật. Tôi đã thay đổi dòng cuối cùng thành

    FOREIGN KEY (parent_id, num) REFERENCES foo(id, num)

và có LRI: không có ràng buộc ràng buộc duy nhất nào cho các khóa đã cho cho bảng tham chiếu "foo" .

Tôi có thể dễ dàng thêm ràng buộc này, nhưng tôi không hiểu tại sao cần thiết, khi một trong các cột được tham chiếu ( id) đã được đảm bảo là duy nhất? Theo cách tôi thấy, các ràng buộc mới sẽ là dư thừa.

Câu trả lời:


11

Đó là một hạn chế của DBMS - trong tất cả chúng theo như tôi biết. Và không chỉ khi thêm một cột mà cả khi sắp xếp lại các cột. Nếu chúng ta có một UNIQUEràng buộc nào đó (a1, a2), chúng ta không thể thêm một FOREIGN KEYđiều đó REFERENCES (a2, a1)trừ khi có một ràng buộc duy nhất về điều (a2, a1)đó về cơ bản là dư thừa.

Sẽ không quá khó để thêm tính năng này như một tính năng:

Khi có một UNIQUEràng buộc trên (a), thì bất kỳ (a, b, c, ..., z)hoặc (b,c, ...a, ...z)kết hợp cũng được đảm bảo UNIQUE.

hoặc khái quát hóa:

Khi có một UNIQUEràng buộc trên (a1, a2, ..., aN), thì bất kỳ (a1, a2, ..., aN, b1, b2, ..., bM)sự kết hợp hoặc sắp xếp lại nào cũng được đảm bảo UNIQUE.

Có vẻ như nó đã không được yêu cầu hoặc nó đã không được coi là ưu tiên đủ cao để được thực hiện.

Bạn luôn có thể đưa ra yêu cầu - trong kênh tương ứng - để tính năng được triển khai. Hoặc thậm chí tự thực hiện nó, nếu DBMS là nguồn mở, như Postgres.


Tôi không chắc nó sẽ khá đơn giản .. Còn về chỉ mục một phần, hoặc các giá trị NULL thì sao? vv .. NULL vẫn có thể hoạt động tốt nếu bạn hài lòng NULL != NULL. Dù sao .. :)
Joishi Bodio

@JoishiBodio Tôi không nghĩ Nulls là một vấn đề. Các ràng buộc ĐỘC ĐÁO cũng có thể được xác định hoặc các cột không thể. Mặc định là nếu bất kỳ cột nào có NULL, thì ràng buộc được thông qua và hàng được chấp nhận.
ypercubeᵀᴹ

Mặc dù vậy, nếu thứ hai, nếu a1, a2, ... aN không thể rỗng và b1, b2, bM thì chúng ta có thể gặp vấn đề. Nhưng tính năng này chắc chắn có thể được triển khai cho các cột không thể rỗng. Điều có lẽ đáng lo ngại là ý nghĩa hiệu quả.
ypercubeᵀᴹ

Tôi quen thuộc với UNIQUE INDEXcác cột ở đâu NULLABLE.. đó là lý do tại sao tôi đề cập đến nó. :) Nhưng tôi đồng ý - trong trường hợp không có NULL (và cũng không phải là một chỉ số một phần), có lẽ nó khá đơn giản.
Joishi Bodio

5

Các khóa ngoại nói chung (không chỉ là tổng hợp) PHẢI trỏ đến một khóa UNIITE của một số loại trong bảng khác. Nếu họ không làm như vậy, sẽ không có tính toàn vẹn dữ liệu quan hệ.

Điều này là phàn nàn bởi vì, trong khi bạn có một khóa duy nhất trên (id) .. bạn KHÔNG có một khóa duy nhất trên (id, num) .. Vì vậy, theo như DB có liên quan, thì cặp (id, num) là không được bảo đảm là duy nhất Chúng ta, như con người, có thể nhận ra nó sẽ là duy nhất, nhưng tôi chắc chắn sẽ có rất nhiều mã bổ sung mà họ sẽ phải thêm vào để làm cho Postgres đủ thông minh để thấy rằng "oh hey .. id được coi là duy nhất , vì vậy id, num cũng phải là duy nhất "..

Tôi sẽ rất ngạc nhiên nếu họ thêm mã đó khi tất cả những gì bạn phải làm là tạo một chỉ mục duy nhất khác trên hai cột để khắc phục sự cố.

Nói rõ hơn, mã họ sẽ phải thêm sẽ không chỉ là trường hợp đơn giản này ... nó sẽ phải xử lý tất cả các trường hợp, ngay cả những trường hợp khóa ngoại nằm trên 4 cột, v.v. Tôi chắc chắn logic sẽ khá phức tạp.

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.