我正在尝试创建一个表,该表可以在两个方向上强制执行两个相同类型列的唯一组合。例如。这将是非法的:
col1 col2
1 2
2 1
我已经想出了这个,但它不起作用:
database=> \d+ friend;
Table "public.friend"
Column | Type | Modifiers | Storage | Stats target | Description
--------------+--------------------------+-----------+----------+--------------+-------------
user_id_from | text | not null | extended | |
user_id_to | text | not null | extended | |
status | text | not null | extended | |
sent | timestamp with time zone | not null | plain | |
updated | timestamp with time zone | | plain | |
Indexes:
"friend_pkey" PRIMARY KEY, btree (user_id_from, user_id_to)
"friend_user_id_to_user_id_from_key" UNIQUE CONSTRAINT, btree (user_id_to, user_id_from)
Foreign-key constraints:
"friend_status_fkey" FOREIGN KEY (status) REFERENCES friend_status(name)
"friend_user_id_from_fkey" FOREIGN KEY (user_id_from) REFERENCES user_account(login)
"friend_user_id_to_fkey" FOREIGN KEY (user_id_to) REFERENCES user_account(login)
Has OIDs: no
是否可以在没有触发器或任何高级魔法的情况下使用约束来编写它?
答案 0 :(得分:13)
Neil解决方案的一个不需要扩展的变体是:
create table friendz (
from_id int,
to_id int
);
create unique index ifriendz on friendz(greatest(from_id,to_id), least(from_id,to_id));
Neil的解决方案允许您使用任意数量的列。
我们都依赖于使用表达式来构建记录的http://www.postgresql.org/docs/9.1/static/indexes-expressional.html
索引答案 1 :(得分:1)
你认为intarray扩展是神奇的吗?
您需要为用户使用int键而不是文本...
这是一个可能的解决方案:
create extension intarray;
create table friendz (
from_id int,
to_id int
);
create unique index on friendz ( sort( array[from_id, to_id ] ) );
insert into friendz values (1,2); -- good
insert into friendz values (2,1); -- bad