Việc sử dụng nhiều ràng buộc duy nhất trên một bảng có bị coi là thiết kế xấu không?


8

Tôi đã xem INSERT INTO .. ON CONFLICT (..) DO UPDATE ..cú pháp của PostgreSQL và nhận ra, bạn không thể thực hiện nhiều kiểm tra ràng buộc duy nhất với nó. Ý tôi là, bạn hoặc tham khảo một chỉ mục duy nhất tổng hợp theo tên cột ON CONFLICT (Name, Symbol)(nếu chỉ mục duy nhất được xác định cho hai cột này) hoặc bạn sử dụng khóa chính. Nếu bạn xác định hai chỉ mục duy nhất riêng biệt cho các cột, bạn chỉ có thể kiểm tra một chỉ mục.

CREATE TABLE student
    (Id int primary key, Name varchar(50), Symbol varchar(50),
      CONSTRAINT col1_unique UNIQUE (Name),
      CONSTRAINT col2_unique UNIQUE (Symbol)
    ); 

INSERT INTO student
    (Id, Name, Symbol)
VALUES
    (1, 'John', 'J'),
    (2, 'David', 'D'),
    (3, 'Will', 'W');

INSERT INTO student
    (Id, Name, Symbol)
VALUES
    (4, 'Jeremy', 'J')
   on conflict(Name) DO UPDATE
   set Name = 'Jeremy';

Có thể ném một lỗi, nói Jlà một bản sao. Tuy nhiên, ví dụ này chỉ đơn giản là một thiết kế xấu, vì Biểu tượng nên ở trong một bảng khác và được kết nối với bảng sinh viên thông qua mối quan hệ một đến nhiều. Đó là lý do tại sao tôi tự hỏi, có lẽ PostgreQuery on conflictđược thiết kế theo cách này, bởi vì bạn có thể LUÔN cấu trúc lại các bảng theo cách mà chỉ có một chỉ mục duy nhất. Là sự thật hay có một lý do khác?

Ví dụ fiddle: http://www.sqlfiddle.com/#!17/9c0ce


bạn có thể LUÔN cấu trúc lại các bảng theo cách, trong đó chỉ có một chỉ mục duy nhất Có EntityA và EntityB. Có 2 trường hợp của mỗi. Bất kỳ phiên bản EntityA nào cũng có thể kết hợp với bất kỳ phiên bản EntityB nào, do đó, có 2 kết hợp có thể có trong đó tất cả các phiên bản được sử dụng. Một trong những kết hợp này được nhận ra, và bạn phải lưu trữ nó. Bây giờ hãy thử tạo một lược đồ trong đó không có bảng nào có 2 dấu duy nhất tồn tại với tất cả các ràng buộc ngăn chặn dữ liệu bất hợp pháp.
Akina

@Akina Tôi đã bỏ lỡ quan điểm của bạn. Nếu hai thực thể được kết nối thông qua nhiều mối quan hệ, bạn tạo một bảng liên kết, lưu trữ khóa ngoại của chúng, do đó không có bảng nào có 2 chỉ mục duy nhất.
appl3r

Một thể hiện chỉ có thể được sử dụng một lần, do đó bạn phải có 2 chỉ mục uniqie trong một bảng được liên kết (bởi mỗi thực thể riêng biệt) để ngăn chặn việc sử dụng thể hiện đã được sử dụng.
Akina

Trong khi đó là sự thật thì điều đó thật phiền phức: hãy xem mẫu trong câu trả lời của Michael Green. Việc chia một bảng đơn giản như vậy thành 4 bảng chắc chắn là một vấn đề đau đầu, vì đây là một từ điển đơn giản, không giống như bạn nên cần tùy chọn "TRÊN CONFLICT".
Walfrat

Câu trả lời:


8

Luôn có Sixth, hoặc Key Domain, dạng thường. Ở đây mỗi cột không khóa trở thành bảng riêng của nó. Vì vậy, bảng 3NF T (Key, Col1, Col2, ..) trở thành T1 (Key, Col1), T2 (Key, Col2), v.v. Những bảng mới yêu cầu tính duy nhất có thể được khai báo.

Tuy nhiên, tôi nghĩ rằng có nhiều ràng buộc duy nhất trên một bảng là hoàn toàn OK. Lấy ví dụ một bảng các quốc gia. Điều này sẽ có, giả sử, một ID, tên, mã ISO, thành phố thủ đô và một số người khác. Mỗi trong số bốn người đầu tiên sẽ là duy nhất. Hơn nữa, nếu chúng ta muốn hệ thống của chúng ta dựa vào từng cá thể duy nhất, tôi tin rằng chúng ta nên xác định các ràng buộc duy nhất trên mỗi. Điều này thực thi sự thật về dữ liệu mà tất cả người tiêu dùng có thể dựa vào.


Bạn có nghĩ rằng thiết kế postgresql chỉ là kết quả của cận thị không? Oracle, SQL Server, DB2 và những người khác đều cung cấp một cách để tính đến tất cả các khóa duy nhất trong tình huống đó (sử dụng MERGEcâu lệnh). Các pg ON CONFLICT DO UPDATE chỉ được thêm vào 9,5 và hạn chế hơn nhiều.
appl3r

1
@ appl3r nó chỉ là một chi tiết thực hiện. Bạn có thể làm ON CONFLICT DO NOTHINGmà không đề cập đến các ràng buộc độc đáo và nó sẽ xem xét tất cả chúng (và không làm gì cả). Khi bạn muốn làm ON CONFLICT DO UPDATE, bạn phải khai báo một cột hoặc một ràng buộc và chỉ một. Các hạn chế có thể được dỡ bỏ trong các phiên bản trong tương lai.
ypercubeᵀᴹ

Tôi hơi bối rối bởi đoạn đầu tiên của bạn. Giả sử chúng ta chia bảng Sinh viên (Id, Tên, Biểu tượng) của OP thành S1 (Id, Tên) và S2 (Id, Biểu tượng) để thử và biến nó thành DK / NF. Điều gì sẽ là các ràng buộc chính (miền và) trên S2 và làm thế nào để họ đảm bảo rằng mỗi sinh viên có cả một Id duy nhất và một Biểu tượng duy nhất?
Ilmari Karonen

1
Câu hỏi là (loại) "Nếu nhiều chỉ số UNIITE vẫn ổn, tại sao PostgreQuery yêu cầu chỉ số trọng tài được chỉ định ON CONFLICT ... DO UPDATEvà không may câu trả lời này không giải quyết được điểm đó.
AndreKR

@AndreKR nó giải quyết (được in đậm): "được (tính năng Postgres này) được thiết kế theo cách này, bởi vì bạn có thể LUÔN cấu trúc lại các bảng theo cách, trong đó chỉ có một chỉ mục duy nhất?" Bạn chắc chắn có thể thêm một câu trả lời khác, giải quyết điểm bạn đề cập
ypercubeᵀᴹ
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.