Điều gì gây ra LRI: không có ràng buộc ràng buộc duy nhất cho các khóa đã cho cho bảng được tham chiếu?


154

Dưới đây, cấu trúc bảng ví dụ đưa ra LRI: không có ràng buộc ràng buộc duy nhất với các khóa đã cho cho bảng được tham chiếu và đã nhìn chằm chằm vào nó trong khi bây giờ tôi không thể hiểu tại sao lỗi này lại phát sinh trong tình huống này.

BEGIN;

CREATE TABLE foo (
    name                VARCHAR(256) PRIMARY KEY
);

CREATE TABLE bar(
    pkey        SERIAL PRIMARY KEY,
    foo_fk      VARCHAR(256) NOT NULL REFERENCES foo(name), 
    name        VARCHAR(256) NOT NULL, 
    UNIQUE (foo_fk,name)
);

CREATE TABLE baz(   
    pkey            SERIAL PRIMARY KEY,
    bar_fk          VARCHAR(256) NOT NULL REFERENCES bar(name),
    name            VARCHAR(256)
);

COMMIT;

Chạy mã trên cho thấy lỗi sau, không có ý nghĩa với tôi, bất cứ ai cũng có thể giải thích tại sao lỗi này phát sinh. Tôi đang sử dụng postgres 9.1

NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo"
NOTICE:  CREATE TABLE will create implicit sequence "bar_pkey_seq" for serial column "bar.pkey"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "bar_pkey" for table "bar"
NOTICE:  CREATE TABLE / UNIQUE will create implicit index "bar_foo_fk_name_key" for table "bar"
NOTICE:  CREATE TABLE will create implicit sequence "baz_pkey_seq" for serial column "baz.pkey"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "baz_pkey" for table "baz"
ERROR:  there is no unique constraint matching given keys for referenced table "bar"


********** Error **********

ERROR: there is no unique constraint matching given keys for referenced table "bar"
SQL state: 42830

Câu trả lời:


188

Đó là bởi vì namecột trên barbàn không có ràng buộc ĐỘC ĐÁO .

Vì vậy, hãy tưởng tượng bạn có 2 hàng trên barbảng có chứa tên 'ams'và bạn chèn một hàng trên bazvới 'ams'trên bar_fk, mà liên tiếp trên barnó sẽ được giới thiệu kể từ khi có hai hàng phù hợp?


1
hoàn hảo ngắn và chính xác và dễ dàng để bắt giải thích!
Alex

79

Trong postgresql, tất cả các khóa ngoại phải tham chiếu một khóa duy nhất trong bảng cha, vì vậy trong barbảng của bạn, bạn phải có một unique (name)chỉ mục.

Xem thêm http://www.postgresql.org/docs/9.1/static/ddl-constraint.html#DDL-CONSTRAINTS-FK và cụ thể:

Cuối cùng, chúng ta nên đề cập rằng khóa ngoại phải tham chiếu các cột là khóa chính hoặc tạo thành một ràng buộc duy nhất.

Nhấn mạnh mỏ.


21
Tại sao PK không được tuyên bố là một ràng buộc duy nhất? không giống như bạn có thể có PK nonunique ...
lưỡng cư

2
Nó phải là duy nhất trên bảng mà nó "trỏ đến", bởi vì nếu không, công cụ cơ sở dữ liệu sẽ không có cách nào để biết bạn đang thực sự đề cập đến hàng nào.
Matteo Tassinari

Phím tổng hợp? @amphibient
Robot quyến rũ

1
Tôi nghĩ rằng chỉ có một khóa duy nhất trên cột được tham chiếu trên bảng cha không chỉ yêu cầu trong postgresql mà còn các RDBMS khác giống như oracle, máy chủ sql, v.v.
Mufachir Hossain

2
Lưu ý rằng câu trả lời cũng đúng với các khóa ngoại tổng hợp, trong đó yêu cầu ràng buộc duy nhất tổng hợp hoặc khóa chính được yêu cầu trên bảng cha.
Ninjakannon

8

Khi bạn thực hiện UNIQUEnhư một ràng buộc mức bảng như bạn đã làm thì định nghĩa của bạn hơi giống với khóa chính tổng hợp xem các ràng buộc ddl , đây là một trích xuất

"This specifies that the *combination* of values in the indicated columns is unique across the whole table, though any one of the columns need not be (and ordinarily isn't) unique."

điều này có nghĩa là một trong hai trường có thể có một giá trị không duy nhất với điều kiện kết hợp là duy nhất và điều này không khớp với ràng buộc khóa ngoại của bạn.

rất có thể bạn muốn các ràng buộc ở mức cột. vì vậy, sau đó xác định chúng là các ràng buộc mức bảng, 'nối' UNIQUEvào cuối định nghĩa cột như name VARCHAR(60) NOT NULL UNIQUEhoặc chỉ định các ràng buộc mức bảng không thường xuyên cho mỗi trường.


Cột mức hạn chế trong hoàn cảnh của tôi sẽ không làm việc tôi thực sự cần phải được xác định một khóa chính hợp chất, nhưng tôi ủng hộ ra khỏi nó bởi vì việc lập bản đồ nó để JPA một chút đau :) nó
AMS

6

Bạn nên có cột tên như một ràng buộc duy nhất. Đây là 3 dòng mã để thay đổi vấn đề của bạn

  1. Trước tiên hãy tìm hiểu các ràng buộc khóa chính bằng cách nhập mã này

    \d table_name

    bạn được hiển thị như thế này ở phía dưới "some_constraint" PRIMARY KEY, btree (column)

  2. Bỏ các ràng buộc:

    ALTER TABLE table_name DROP CONSTRAINT some_constraint
  3. Thêm một cột khóa chính mới với một cột hiện có:

    ALTER TABLE table_name ADD CONSTRAINT some_constraint PRIMARY KEY(COLUMN_NAME1,COLUMN_NAME2);

Đó là tất cả.

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.