【问题标题】:postgres many to one unique constraintpostgres 多对一唯一约束
【发布时间】:2020-11-23 09:36:21
【问题描述】:

我很好奇是否有办法编写唯一约束来支持以下情况。

假设我有一个表table1,其中包含有关用户的事实,有四列:

  • user_id:用户的唯一 ID
  • source:细节从何而来
  • d1:事实的维度 1
  • d2:事实的维度 2

以下是该表中的数据示例:

| row_id | user_id | source | d1     | d2      |
|--------|---------|--------|--------|---------|
| 1      | aaa111  | foo    | bar    | 123     |
| 2      | aaa111  | foo    | baz    | 'horse' |
| 3      | aaa111  | scrog  | bar    | 123     |
| 4      | bbb222  | foo    | goober | 456     |

目前,source + d1 + d2 存在唯一约束。这很好,因为它允许同一用户拥有(d1,d2) 的重复项,只要他们有不同的source。 第 1 行和第 3 行为用户 aaa111 演示了这一点。

但是,此约束不会阻止添加下一行...

| row_id | user_id | source | d1     | d2      |
|--------|---------|--------|--------|---------|
| 1      | aaa111  | foo    | bar    | 123     |
| 2      | aaa111  | foo    | baz    | 'horse' |
| 3      | aaa111  | scrog  | bar    | 123     |
| 4      | bbb222  | foo    | goober | 456     |
| 5      | bbb222  | turnip | baz    | 'horse' |  <---- allowed new row

...因为source 对于第 2 行和第 5 行是不同的。

我想添加一个唯一约束,其中(d1,d2) 的组合可能只存在于一个单个 user_id

换句话说,单个用户可以根据需要拥有多个唯一的(source, d1, d2) 组合,但不能与另一个user_id 共享(d1,d2)

这个数据模型在支持这个约束方面是否存在根本缺陷?还是有一个独特的约束可能有助于强制执行?提前感谢您的任何建议。

【问题讨论】:

    标签: postgresql unique-constraint


    【解决方案1】:

    这是一个条件约束,您可以使用触发器 BEFORE INSERT OR UPDATE 在违反约束时引发异常:

    CREATE OR REPLACE FUNCTION check_user_combination() RETURNS trigger AS
    $$
    DECLARE
      vCheckUser INTEGER;
    BEGIN
      SELECT INTO vCheckUser user_id
      FROM table1 
      WHERE d1 = NEW.d1 
        AND d2 = NEW.d2 
        AND user_id <> NEW.user_id;
    
      IF vCheckUser IS NOT NULL THEN
        RAISE EXCEPTION 'User % have already d1=% and d2=%',vCheckUser,NEW.d1, NEW.d2;
      END IF;
      RETURN NEW;
    END;
    $$
      language 'plpgsql';
    
    CREATE TRIGGER tr_check_combination BEFORE INSERT OR UPDATE ON table1 FOR EACH ROW EXECUTE PROCEDURE check_user_combination();
    

    这可以防止插入或更新相同 d1 和 d2 的其他用户。

    【讨论】:

    • 绝对完美。非常感谢!
    猜你喜欢
    • 2015-03-06
    • 1970-01-01
    • 2017-07-07
    • 1970-01-01
    • 2014-06-20
    • 2014-06-25
    • 2010-12-22
    • 1970-01-01
    相关资源
    最近更新 更多