Lưu trữ dưới dạng mảng (không chuẩn hóa)
Tôi sẽ xem xét mô-đun bổ sung intarray
cung cấp các chức năng thuận tiện (và nhanh chóng) uniq()
và sort()
. Trong cài đặt Postgres hiện đại điển hình, nó dễ dàng như sau:
CREATE EXTENSION intarray;
Sử dụng những thứ này, một CHECK
đơn giản ràng buộc có thể thực thi tăng dần mảng có khác biệt các phần tử.
CHECK (uniq(sort(cat_arr)) = cat_arr)
Bạn có thể ngoài ra (tùy chọn) có một trình kích hoạt chuẩn hóa các giá trị mảng ON INSERT OR UPDATE
tự động. Sau đó, bạn chỉ cần vượt qua bất kỳ mảng (có thể không được sắp xếp và có lỗi) và mọi thứ đều hoạt động. Như:
CREATE OR REPLACE FUNCTION trg_search_insup_bef()
RETURNS trigger AS
$func$
BEGIN
NEW.cat_arr := uniq(sort(NEW.cat_arr);
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
CREATE TRIGGER insup_bef
BEFORE INSERT OR UPDATE OF cat_arr ON search
FOR EACH ROW
EXECUTE PROCEDURE trg_search_insup_bef();
Phần xâm nhập mô-đun bổ sung là tùy chọn, có những cách khác:
Nhưng các hàm intarray mang lại hiệu suất vượt trội.
Sau đó bạn chỉ có thể tạo một UNIQUE
ràng buộc trên cột mảng để thực thi tính duy nhất của toàn bộ mảng.
UNIQUE (cat_arr)
Tôi đã viết thêm về những ưu điểm của việc kết hợp các ràng buộc (rất nghiêm ngặt và đáng tin cậy) với các trình kích hoạt (ít đáng tin cậy hơn nhưng thuận tiện hơn) trong câu trả lời có liên quan này chỉ hai ngày trước:
Nếu, đối với mỗi kết hợp, tất cả những gì bạn cần lưu trữ trên mỗi danh mục là ID (và không có thông tin bổ sung), thì điều này phải đủ tốt.
Tuy nhiên , tính toàn vẹn của tham chiếu không dễ dàng được đảm bảo theo cách này. Không có ràng buộc khóa ngoại nào cho các phần tử mảng (chưa) - như được ghi lại trong liên kết của bạn
:Nếu một trong các danh mục bị xóa hoặc bạn thay đổi ID, tham chiếu sẽ bị hỏng ...
Lược đồ chuẩn hóa
Nếu bạn cần lưu trữ nhiều hơn hoặc bạn muốn sử dụng một lược đồ chuẩn hóa để thực thi tính toàn vẹn của tham chiếu hoặc vì lý do nào đó, bạn cũng có thể làm điều đó và thêm một trình kích hoạt để điền vào một chế độ xem được thực hiện thủ công (một bảng dự phòng) và thực thi tính duy nhất theo cách tương tự:
CREATE TABLE search (
search_id serial PRIMARY KEY
, ... more columns
);
CREATE TABLE cat (
cat_id serial PRIMARY KEY
, cat text NOT NULL
);
CREATE TABLE search_cat (
search_id int REFERENCES search ON DELETE CASCADE
, cat_id int REFERENCES cat
, PRIMARY KEY (search_id, cat_id)
);
Câu trả lời có liên quan (không dành cho các kết hợp duy nhất, mà dành cho các phần tử duy nhất) thể hiện trình kích hoạt: