2013-04-08 37 views
13
CREATE TABLE foo (
    dt  AS DATE NOT NULL, 
    type AS TEXT NOT NULL, 
    CONSTRAINT unique_dt_type UNIQUE(dt,type) -- check constraint(?) 
) 

Có lỗi khi cố nghĩ đúng cú pháp để tạo ra ràng buộc duy nhất khi chỉ tồn tại một điều kiện nhất định.SQL: Ràng buộc duy nhất khi cột là một giá trị nhất định

Given, type có thể có giá trị A-F, chỉ có thể có một A mỗi ngày, nhưng có thể có nhiều B-F. Ví dụ về bảng tốt:

2010-01-02 | 'A' -- only one 
2010-01-02 | 'B' -- can have multiple 
2010-01-02 | 'B' 
2010-01-02 | 'B' 
2010-01-02 | 'C' -- can have multiple 
2013-01-02 | 'A' -- only one 
2010-01-02 | 'B' -- can have multiple 
2010-01-02 | 'B' 
2013-01-02 | 'F' -- can have multiple 
2013-01-02 | 'F' 

Đã đọc kiểm tra đọc/cú pháp duy nhất nhưng không có ví dụ nào. CHECK đến gần nhưng chỉ giới hạn nó đến một phạm vi và không được sử dụng kết hợp với một kịch bản UNIQUE. Cũng cố gắng tìm kiếm, nhưng kỹ năng tìm kiếm của tôi hoặc là không lên đến ngang, hoặc không có bất kỳ câu hỏi tương tự.

+0

Bạn có thể easely làm điều đó bằng cách sử dụng kích hoạt! – Houari

+0

@Houari: Nghe có vẻ đầy hứa hẹn, bạn có ví dụ nhanh không? Tôi đã tìm thấy một số kết quả khi tôi tìm kiếm 'sql có điều kiện duy nhất', nhưng không thành công (chúng đã được ghi ngày) – vol7ron

+1

Tôi có thể đã tìm thấy giải pháp trong câu hỏi được nêu ở đây: http://stackoverflow.com/q/987099/183181, nếu 'where' được cho phép trong khi tạo chỉ mục – vol7ron

Trả lời

17

PostgreSQL có thể giải quyết nhu cầu của bạn thông qua tính năng "Chỉ mục một phần". Trong thực tế, điều này được thực hiện bằng cách thêm mệnh đề where vào câu lệnh tạo chỉ mục.

mẫu:

CREATE INDEX my_partial_ix ON my_sample_table (my_sample_field) 
WHERE NOT (my_sample_field = 'duplicates ok'); 

Hãy xem ở đây: http://www.postgresql.org/docs/current/interactive/indexes-partial.html

Đặc biệt chú ý đến phần Example 11-3. Setting up a Partial Unique Index. Nó đưa ra một ví dụ phù hợp với mục tiêu đã nêu của bạn.

1

Sử dụng một kích hoạt:

CREATE OR REPLACE FUNCTION "CheckConstraint"() 
    RETURNS trigger AS 
$BODY$declare 
already_exists boolean; 
begin 

if new.foo_type='A' then 
select count(*) >0 from foo where foo_type='A' and dt=new.dt INTO already_exists; 
if already_exists then 
raise exception 'date % already have an A', new.dt; 
end if; 
end if; 

return new; 
end;$BODY$ 
    LANGUAGE plpgsql VOLATILE 
    COST 100; 
+2

Cách quá phức tạp. Điều này sẽ không quy mô và sử dụng một chỉ số một phần là nhanh hơn và mạnh mẽ hơn nhiều. –

+0

Ngoài ra, chỉ mục sẽ tự động phục vụ để tăng tốc các truy vấn phù hợp. Chỉ có nhược điểm nhỏ: chỉ số cần một số không gian đĩa. –

Các vấn đề liên quan