您可以使用触发器来模拟具有所需属性的唯一约束。这样的事情会做的伎俩:
create or replace function sort_of_unique() returns trigger as $$
declare
got_one boolean;
begin
select exists(
select 1
from your_table
where header_id != new.header_id
and value = new.value
) into got_one;
if got_one then
raise exception 'Uniqueness violation in your_table';
end if;
return new;
end;
$$ language plpgsql;
create trigger sort_of_unique_trigger
before insert or update on your_table
for each row execute procedure sort_of_unique();
然后你会得到这样的事情发生:
=> insert into your_table (id, header_id, value) values (1, 1, 'a');
=> insert into your_table (id, header_id, value) values (2, 1, 'a');
=> insert into your_table (id, header_id, value) values (3, 2, 'a');
ERROR: Uniqueness violation in your_table
=> insert into your_table (id, header_id, value) values (3, 2, 'b');
=> update your_table set value = 'a' where id = 3;
ERROR: Uniqueness violation in your_table
您可以通过WHERE子句附加到指数创建partial unique indexes。这允许您将唯一性约束应用于表的切片;然而,我想不出一种方法来获取WHERE子句来指定一个“反切片”,所以我没有看到一种方法来使这部分索引工作。我可能会错过一些明显的事情。
这是一个合理的方法。你也可以使用'select exists'(从表中选择1 ...))'而不是'limit',这个习惯用法通常被优化器识别。 – 2012-02-17 16:59:35