postgres多对一唯一约束
postgres many to one unique constraint
我很好奇是否有办法编写唯一约束来支持以下情况。
假设我有 table table1
关于用户的事实,有四列:
user_id
:用户的唯一 ID
source
: 细节来源
d1
:事实的维度 1
d2
:事实的维度 2
下面是这个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 插入或更新其他用户。
我很好奇是否有办法编写唯一约束来支持以下情况。
假设我有 table table1
关于用户的事实,有四列:
user_id
:用户的唯一 IDsource
: 细节来源d1
:事实的维度 1d2
:事实的维度 2
下面是这个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 插入或更新其他用户。