man*_*iam 8 postgresql database-design primary-key unique-constraint
我有两张桌子:一张user桌子和一张friendship桌子。假设friendship表格如下所示:
friendship
------------
user_one_id
user_two_id
other_fields
Run Code Online (Sandbox Code Playgroud)
我需要强制执行和忽略ordering值组合的唯一性,因此:(user_one_id, user_two_id)
user_one_id | user_two_id
------------+------------
1 | 2
2 | 1 -- the DBMS should throw a unique constraint error when trying to insert a row like this one.
Run Code Online (Sandbox Code Playgroud)
另外重要的一点是,user_one_id代表发起的friendship,并user_two_id代表收件人,所以我不能只是做了两个“小”的ID user_one_id。
问题
有没有办法使用约束来做到这一点,还是应该以其他方式实现?
根据你的评论,
对于我的用例,user_one_id 代表友谊的发起者,而 user_two_id 代表友谊的接收者。所以我不能只使用最低值作为 user_one_id。
嗯,你仍然可以做到。您的用例只是排除了行约束以确保这一点。你想要的是使用表格约束,就像这样。
CREATE TABLE friendship (
user_one_id int NOT NULL,
user_two_id int NOT NULL,
CHECK (user_one_id != user_two_id ),
PRIMARY KEY (user_one_id, user_two_id)
);
-- you can do least first if you want. doesn't matter.
CREATE UNIQUE INDEX ON friendship (
greatest(user_one_id, user_two_id),
least(user_one_id, user_two_id)
);
Run Code Online (Sandbox Code Playgroud)
我们有很多事情要做……我们确保。
NOT NULLUNIQUE (user_one_id, user_two_id)这留下了一个剩余的交换唯一性问题,我们使用索引实现的自定义唯一表约束来解决该问题。
布丁中的证明
INSERT INTO friendship VALUES ( 1,2 );
INSERT 0 1
test=# INSERT INTO friendship VALUES ( 2,1 );
ERROR: duplicate key value violates unique constraint friendship_greatest_least_idx"
DETAIL: Key ((GREATEST(user_one_id, user_two_id)), (LEAST(user_one_id, user_two_id)))=(2, 1) already exists.
Run Code Online (Sandbox Code Playgroud)
作为一个重要的友好说明,你的名字很愚蠢。关系很好。在生产中,请给它们起更好的名字..
friendship
----------
request_initiator
request_target
other_fields
Run Code Online (Sandbox Code Playgroud)