【问题标题】:Postgresql enforce unique two-way combination of columnsPostgresql 强制列的唯一双向组合
【发布时间】:2015-05-04 18:03:32
【问题描述】:

我正在尝试创建一个表,该表将强制两个相同类型的列的唯一组合 - 在两个方向上。例如。这将是非法的:

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

是否可以在不使用触发器或任何高级魔法的情况下仅使用约束来编写此代码?

【问题讨论】:

    标签: postgresql unique combinations


    【解决方案1】:

    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 的解决方案允许您使用任意数量的列。

    我们都依赖于使用表达式来构建记录在案的索引 https://www.postgresql.org/docs/current/indexes-expressional.html

    【讨论】:

    • 好兄弟。很简单
    • 谢谢。在任何地方都找不到这个。
    • 如何使用 upsert 完成这项工作? ON CONFLICT (col1, col2) 表单似乎不起作用,因为这是一个索引。
    • 对于 ON CONFLICT DO NOTHING 情况,您无需指定任何内容。对于 ON CONFLICT DO UPDATE 情况,我认为您不需要提供列列表 (col1, col2) 但如果我没记错的话,您可以直接指定索引名称。
    【解决方案2】:

    你认为 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
    

    http://sqlfiddle.com/#!15/c84b7/1

    【讨论】:

      猜你喜欢
      • 2012-12-22
      • 2017-04-23
      • 2023-03-27
      • 2011-03-18
      • 1970-01-01
      • 1970-01-01
      • 2014-06-01
      • 1970-01-01
      相关资源
      最近更新 更多