Trying to create a conditional unique index in postgresql but unable to do so and getting this error
Query 1 ERROR: ERROR: cannot use subquery in index predicate
LINE 3: WHERE (
^
this is how my query looks like
CREATE UNIQUE INDEX conditional_unique_index
ON test_table (a, b)
WHERE (
SELECT COUNT(*)
FROM test_table t2
WHERE t2.a = test_table.a AND t2.b = test_table.b
) = 1;
My requirement is this:
CREATE TABLE test_table (
a integer,
b integer,
c integer
);
INSERT INTO test_table (a, b, c) VALUES
(1, 2, 22),
(1, 2, 22),
(1, 2, 22),
(1, 3, 34),
(2, 3, 26),
(2, 3, 26);
the conditions are if there are multiple rows with the same values in columns (a, b) then in the column c values must be the same like this (1, 2, 22),(1, 2, 22),(1, 2, 22); and this is not allowed (1, 2, 22),(1, 2, 23),(1, 2, 22); c must be same here (1, 2, 23)
now the second condition is if columns (a, b) are unique then c also should be unique
like this (1, 3, 34),(2, 3, 26); and this is not allowed (1, 3, 34),(2, 3, 34); same values for c is not allowed in this case
so far for this 1st case, I have managed it by using triggers
CREATE OR REPLACE FUNCTION check_conditional_unique() RETURNS TRIGGER AS $$
BEGIN
IF EXISTS (
SELECT 1
FROM test_table t2
WHERE t2.a = NEW.a AND t2.b = NEW.b AND t2.c <> NEW.c
) THEN
RAISE EXCEPTION 'Duplicate values in c for the same a and b combination.';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_check_conditional_unique
BEFORE INSERT ON test_table
FOR EACH ROW
EXECUTE FUNCTION check_conditional_unique();
but for this 2nd case I’m facing issue this queury is wrong what i have wrote for this
CREATE UNIQUE INDEX conditional_unique_index
ON test_table (a, b)
WHERE (
SELECT COUNT(*)
FROM test_table t2
WHERE t2.a = test_table.a AND t2.b = test_table.b
) = 1;
2
Answers
You can handle both cases you described, in your trigger, without the constraint: demo
The examples you gave don’t match what
unique
or partial unique constraints are for; as long as they share a commonc
you do need duplicate pairs of(a,b)
to be allowed.The classical solution for this is no normalize the data model by splitting it into several tables. Observe that
c
is functionally dependent on(a, b)
. So you could devise one table like this:Since
a
andb
can occur multiple times in your setup, you then have another table like this:The primary key was added because every table should/must have one.
Your table then becomes a view: