PostgreSQL - chèn / cập nhật vi phạm các ràng buộc khóa ngoại


11

Tôi là một người mới trong postgreSQL. Tôi có 3 bảng, một bảng tham chiếu các khóa chính của 2 bảng khác. Nhưng tôi không thể chèn dữ liệu vào Table3. Xem mã dưới đây:

DROP TABLE Table1 CASCADE;
CREATE TABLE Table1(
  "DataID" bigint NOT NULL DEFAULT '0',
  "AdData" integer DEFAULT NULL,
  PRIMARY KEY ("DataID")
);

DROP TABLE IF EXISTS Table2 CASCADE;
CREATE TABLE Table2 (
  "Address" numeric(20) NOT NULL DEFAULT '0',
  "Value" numeric(20) DEFAULT NULL,
  PRIMARY KEY ("Address")
);

DROP TABLE IF EXISTS Table3 CASCADE; 
CREATE TABLE table3 (   
  "ID" bigint NOT NULL DEFAULT '0',   
  "DataID" bigint DEFAULT NULL,   
  "Address" numeric(20) DEFAULT NULL,   
  "Data" bigint DEFAULT NULL,
   PRIMARY KEY ("ID"),   
   FOREIGN KEY ("DataID") REFERENCES Table1("DataID") on delete cascade on update cascade,   
   FOREIGN KEY ("Address") REFERENCES Table2("Address") on delete cascade on update cascade
);

LRI: chèn hoặc cập nhật trên bảng "Bảng 3" vi phạm ràng buộc khóa ngoại "Bảng3_DataID_fkey" CHI TIẾT: Khóa (DataID) = (27856) không có trong bảng "Bảng 1".

Khi tôi cố gắng chèn dữ liệu vào 3 bảng thì đã xảy ra lỗi. Tôi đã giới thiệu tài liệu postgreSQL và thay đổi mã của mình như sau: (Thật không may, nó đã hiển thị một lỗi khác)

DROP TABLE Table1 CASCADE;
CREATE TABLE Table1(
  "DataID" bigint NOT NULL DEFAULT '0',
  "AdData" integer DEFAULT NULL,
  PRIMARY KEY ("DataID")
);

DROP TABLE IF EXISTS Table2 CASCADE;
CREATE TABLE Table2 (
  "Address" numeric(20) NOT NULL DEFAULT '0',
  "Value" numeric(20) DEFAULT NULL,
  PRIMARY KEY ("Address")
);

DROP TABLE IF EXISTS Table3 CASCADE; 
CREATE TABLE table3 (   
  "ID" bigint NOT NULL DEFAULT '0',   
  "DataID" bigint DEFAULT NULL REFERENCES Table1 ON DELETE RESTRICT,
  "Address" numeric(20) DEFAULT NULL REFERENCES Table2 ON DELETE CASCADE, 
  "Data" bigint DEFAULT NULL,
   PRIMARY KEY ("ID"),   
   PRIMARY KEY("DataID", "Address")
);

LRI: nhiều khóa chính cho bảng "Bảng 3" không được phép LINE 65: KEY PRIMARY ("DataID", "Địa chỉ")

Xin hãy giúp tôi ... Làm thế nào tôi có thể tạo tài liệu tham khảo?

Tôi đã thay đổi IDnhư UNIQUEvà loại bỏ các dòng PRIMARY KEY ("ID"). Tại thời điểm đó, nó hiển thị một lỗi khác như:

LRI: giá trị khóa trùng lặp vi phạm ràng buộc duy nhất "Table3_pkey"

Câu trả lời:


16

Có một vài vấn đề với bảng của bạn. Tôi sẽ cố gắng giải quyết các khóa ngoại trước, vì bạn đã hỏi về chúng :)

Nhưng trước đó, chúng ta nên nhận ra rằng hai bộ bảng (ba bộ đầu tiên bạn đã tạo và bộ thứ hai mà bạn đã tạo sau khi bỏ bộ thứ nhất) giống nhau. Tất nhiên, định nghĩa Table3trong lần thử thứ hai của bạn có lỗi cú pháp và logic, nhưng ý tưởng cơ bản là:

CREATE TABLE table3 (   
  "ID" bigint NOT NULL DEFAULT '0',   
  "DataID" bigint DEFAULT NULL,   
  "Address" numeric(20) DEFAULT NULL,   
  "Data" bigint DEFAULT NULL,
   PRIMARY KEY ("ID"),   
   FOREIGN KEY ("DataID") REFERENCES Table1("DataID") on delete cascade on update cascade,   
   FOREIGN KEY ("Address") REFERENCES Table2("Address") on delete cascade on update cascade
);

Định nghĩa này cho PostgreSQL đại khái như sau: "Tạo một bảng có bốn cột, một cột sẽ là khóa chính (PK), các cột khác có thể được NULL. Nếu một hàng mới được chèn, hãy kiểm tra DataIDAddress: nếu chúng có chứa giá trị không phải là NULL ( nói 27.856), sau đó kiểm tra Table1cho DataIDTable2cho Address. Nếu không có giá trị như vậy trong những bảng biểu, sau đó trả về một lỗi." Điểm cuối cùng mà bạn đã thấy đầu tiên:

ERROR: insert or update on table "Table3" violates foreign key constraint 
    "Table3_DataID_fkey" DETAIL: Key (DataID)=(27856) is not present in table "Table1".

Rất đơn giản: nếu không có hàng ở Table1đâu DataID = 27856, thì bạn không thể chèn hàng đó vào Table3.

Nếu bạn cần hàng đó, bạn nên đầu tiên chèn một hàng vào Table1với DataID = 27856, và chỉ sau đó cố gắng chèn vào Table3. Nếu điều này dường như không phải là những gì bạn muốn, xin vui lòng mô tả trong một vài câu những gì bạn muốn đạt được, và chúng tôi có thể giúp với một thiết kế tốt.


Và bây giờ về các vấn đề khác.

Bạn xác định PK của mình là

CREATE all_your_tables (
    first_column NOT NULL DEFAULT '0',   
    [...]
    PRIMARY KEY ("ID"),  

Khóa chính có nghĩa là tất cả các mục trong đó khác nhau, nghĩa là các giá trị là UNIQUE. Nếu bạn cung cấp một tĩnh DEFAULT(như '0') cho một UNIQUEcột, bạn sẽ gặp những bất ngờ tồi tệ mọi lúc. Đây là những gì bạn nhận được trong thông báo lỗi thứ ba của bạn.

Hơn nữa, '0'có nghĩa là một chuỗi văn bản, nhưng không phải là một số ( biginthoặc numerictrong trường hợp của bạn). Sử dụng đơn giản 0thay vào đó (hoặc hoàn toàn không sử dụng nó, như tôi đã viết ở trên).

Và một điểm cuối cùng (tôi có thể sai ở đây): trong Table2, Addresstrường của bạn được đặt thành numeric(20). Đồng thời, nó là PK của bảng. Tên cột và kiểu dữ liệu cho thấy địa chỉ này có thể thay đổi trong tương lai. Nếu điều này là đúng, thì đó là một lựa chọn rất tồi cho PK. Hãy suy nghĩ về kịch bản sau đây: bạn có một địa chỉ '1234567890454', có một đứa trẻ Table3giống như

ID        DataID           Address             Data
123       3216547          1234567890454       654897564134569

Bây giờ địa chỉ đó xảy ra để thay đổi sang một cái gì đó khác. Làm thế nào để bạn thực hiện hàng con của bạn Table3theo cha mẹ của nó đến địa chỉ mới? (Có giải pháp cho việc này, nhưng có thể gây ra nhiều nhầm lẫn.) Nếu đây là trường hợp của bạn, hãy thêm một cột ID vào bảng của bạn, nơi sẽ không chứa bất kỳ thông tin nào từ thế giới thực, nó sẽ chỉ đơn giản là một giá trị nhận dạng (đó là , ID) cho một địa chỉ.


Cảm ơn lời đề nghị có giá trị của bạn. Tôi sẽ cố gắng để thiết kế tốt hơn dựa trên đề xuất của bạn. Bây giờ lỗi đầu tiên được giải quyết.
Haseena

0

Tất cả phụ thuộc vào những gì bạn muốn làm với dữ liệu.

Ví dụ đầu tiên - bạn muốn có dữ liệu nhất quán trong tất cả các bảng, nhưng bạn cố gắng chèn các giá trị không khớp với Bảng1.

Ví dụ thứ hai - bạn không muốn có dữ liệu nhất quán, nhưng hãy thử làm một cái gì đó khác, không biết chính xác cái gì. Bảng không thể có nhiều hơn một khóa chính.

Ví dụ thứ ba - bạn vẫn không biết những gì bạn muốn đạt được và đặt ràng buộc ĐỘC ĐÁO trên cột có thể có cùng giá trị nhiều lần.

Nếu bạn chỉ muốn chèn dữ liệu của mình - hãy loại bỏ các tham chiếu khóa ngoại trong ví dụ đầu tiên. Nếu bạn muốn có dữ liệu nhất quán trong tất cả các bảng - hãy thực hiện dọn dẹp dữ liệu và sau đó chèn vào các bảng VỚI các ràng buộc khóa ngoài.

tl; dr: để chèn dữ liệu của bạn vào Bảng 3 với mã từ ví dụ đầu tiên - chèn các giá trị còn thiếu vào cột Table1.DataID tồn tại trong Bảng3.DataId.

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.