postgres多对一唯一约束

postgres many to one unique constraint

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

假设我有 table table1 关于用户的事实,有四列:

下面是这个table中的数据示例:

| 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

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

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

换句话说,一个用户可以根据需要拥有任意数量的独特 (source, d1, d2) 组合,但不能与另一个 user_id.

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