I'm trying to prevent the user to insert more then 1 unique array of strings into the table.
I have created a Unique Constraint on the array: CONSTRAINT users_uniq UNIQUE(usersArray)
,
but the user can still insert the same values to the array but in a different order. My table:
id | usersArray |
---|---|
1 | {011,123} |
2 | {123,011} // should not be possible |
Input : {011,123} --> error unique // the right error
Input : {123,011} --> Worked // Should have return an error instead
How can I make the value {123,011} and {011,123} considered the same?
CodePudding user response:
A trigger which enforces the order of the items in the array could be one approach. Here's an example:
CREATE TABLE test ( arr int ARRAY, unique (arr) );
CREATE FUNCTION test_insert_trig_func()
RETURNS trigger AS $$
BEGIN
NEW.arr := ARRAY(SELECT unnest(NEW.arr) ORDER BY 1);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER test_insert_trig
BEFORE INSERT ON test
FOR EACH ROW
EXECUTE PROCEDURE test_insert_trig_func()
;
INSERT INTO test VALUES ('{1, 2}');
INSERT INTO test VALUES ('{2, 1}'); -- Generates a unique constraint violation
SELECT * FROM test;
The result:
arr |
---|
{1,2} |
CodePudding user response:
The trigger solution is not transparent as it is actually modifying the data. Here is an alternative. Create array_sort
helper function (it might be useful for other cases too) and an unique index using it.
create or replace function array_sort (arr anyarray) returns anyarray immutable as
$$
select array_agg(x order by x) from unnest(arr) x;
$$ language sql;
create table t (arr integer[]);
create unique index tuix on t (array_sort(arr));
Demo
insert into t values ('{1,2,3}'); -- OK
insert into t values ('{2,1,3}'); -- unique violation
select * from t;
arr |
---|
{1,2,3} |