I'm curious if there is a way to write a unique constraint to support the following situation.
Suppose I have table table1
with facts about a user, with four columns:
user_id
: unique id for user source
: where the detail came from d1
: dimension 1 of the fact d2
: dimension 2 of the fact The following is an example of data in this 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 |
Currently, a unique constraint exists on source + d1 + d2
. This is good, because it allows the same user to have duplicates of (d1,d2)
, as long as they have a different source
. Rows #1 and #3 demonstrate this for user aaa111
.
However, this constraint does not prevent the following row from getting added...
| 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
...because source
is different for rows #2 and #5.
I would like to add a unique constraint where the combination of (d1,d2)
may only exist for a single user_id
.
Said another way, a single user can have as many unique (source, d1, d2)
combinations as needed, but cannot share (d1,d2)
with another user_id
.
Is this data model fundamentally flawed to support this constraint? or is there a unique constraint that might help enforce this? Thanks in advance for any suggestions.
It's a conditional-constraint, you can use a trigger BEFORE INSERT OR UPDATE that raise exception when violate the constraint:
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();
This prevent insert or update additional user for the same d1 and d2.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.