无论顺序如何,数据对的表约束

时间:2015-11-20 20:15:54

标签: sql postgresql

我有两张桌子;朋友和用户。

Users表,略微简化:

CREATE TABLE users (
    id bigserial NOT NULL,
    fname text,
    lname text,
    username text,
    created timestamp without time zone DEFAULT now(),
    CONSTRAINT users_pkey PRIMARY KEY (id)
)

Friends表是一个连接表

CREATE TABLE friends
(
    user_id bigint,
    friend_id bigint,
    accepted boolean DEFAULT false
)

因此,朋友表只是将一个用户映射到另一个用户,因此用户1可以是用户2的朋友。

我的问题:如何约束表格,使两对(1,2),(2,1)不插入表格?

我知道我可以unique (user_id , friend_id)来阻止插入像(1,2)这样的重复行......

但是,如果(1,2)已经存在,如何阻止插入(2,1)?

1 个答案:

答案 0 :(得分:3)

在表达式上使用索引:

create unique index unq_friends_user_friend
    on (least(user_id, friend_id), greatest(user_id, friend_id));

编辑:

我需要详细说明,因为另一个答案。

请注意,这种方法涉及数据库中的一行代码(好吧,我承认我在答案中将其分为两部分;)

尝试在应用程序层复制此代码需要:

  • 检查是否存在任何一对的复杂查询。
  • 我应该注意到这个复杂的查询很难优化(特别是在答案中提出)。
  • 运行查询并在任何insert之前检查结果的应用程序代码。
  • 哦,update也是如此。嗯,它留给读者作为练习如何处理更新,特别是多行更新。

经历了所有这些麻烦之后,你仍然遇到了种族问题。两个线程可能会尝试插入相同的两个朋友。两者都没有看到冲突。两者都插入。现在,你有重复。

这使得单线解决方案真的很简单。