Postgresql postgres多对一唯一约束

Postgresql postgres多对一唯一约束,postgresql,unique-constraint,Postgresql,Unique Constraint,我很好奇是否有一种方法可以编写一个惟一的约束来支持以下情况 假设表1中有一个用户的事实,共有四列: 用户id:用户的唯一id 资料来源:细节来自哪里 d1:事实的维度1 d2:事实的维度2 以下是此表中的数据示例: | row_id | user_id | source | d1 | d2 | |--------|---------|--------|--------|---------| | 1 | aaa111 | foo | bar | 123

我很好奇是否有一种方法可以编写一个惟一的约束来支持以下情况

假设表1中有一个用户的事实,共有四列:

用户id:用户的唯一id 资料来源:细节来自哪里 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的副本,只要它们具有不同的源。 第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
…因为第2行和第5行的源不同

我想添加一个唯一的约束,其中d1和d2的组合可能只存在于单个用户id中

换句话说,单个用户可以根据需要拥有任意多个唯一源、d1、d2组合,但不能与其他用户共享d1、d2


这种数据模型在支持这种约束方面是否存在根本缺陷?或者是否有一个独特的约束可以帮助实施这一点?提前感谢您的建议。

这是一个条件约束,您可以在插入或更新之前使用触发器,在违反约束时引发异常:

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插入或更新其他用户。

绝对完美。非常感谢!