Created
April 2, 2021 21:11
-
-
Save jirutka/41981b6e972bf6aa3b710b927fd2954e to your computer and use it in GitHub Desktop.
PostgreSQL constraint trigger to check if each array element is unique within the table
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
------------------------------------------------------------------------------- | |
-- EXAMPLE USAGE | |
-- | |
-- create table specialization ( | |
-- id bigserial, | |
-- name text not null, | |
-- study_plan_codes text[] not null default '{}' | |
-- ) | |
-- | |
-- create constraint trigger study_plan_codes_unique_check | |
-- after insert or update of study_plan_codes on specialization | |
-- for each row | |
-- when (cardinality(NEW.study_plan_codes) > 0) | |
-- execute function trg_check_array_elements_column_uniq('study_plan_codes'); | |
------------------------------------------------------------------------------- | |
create function trg_check_array_elements_column_uniq () | |
returns trigger | |
language plpgsql | |
as $$ | |
declare | |
col_name text := TG_ARGV[0]; | |
duplicates text; | |
ok boolean; | |
begin | |
if TG_NARGS != 1 then | |
raise 'invalid number of arguments: expected 1, but given %', TG_NARGS using | |
detail = 'The function was called from trigger "' || TG_NAME || '".'; | |
end if; | |
execute format(' | |
select not exists ( | |
select 1 | |
from %2$I | |
where %1$I && $1.%1$I | |
offset 1 | |
)', | |
col_name, TG_TABLE_NAME) | |
into strict ok | |
using NEW; | |
if ok then | |
return null; | |
else | |
execute format(' | |
select string_agg(quote_literal(value), '', '') | |
from ( | |
select unnest(%1$I) as value | |
from %2$I | |
where %1$I && $1.%1$I | |
group by value | |
having count(*) > 1 | |
) x', | |
col_name, TG_TABLE_NAME) | |
into strict duplicates | |
using NEW; | |
raise 'duplicate array element in column "%"', col_name using | |
detail = 'Following element(s) already exist in table "' || TG_TABLE_NAME || '": ' || duplicates || '.', | |
column = col_name, | |
table = TG_TABLE_NAME, | |
errcode = 'unique_violation'; | |
end if; | |
end; | |
$$; | |
comment on function trg_check_array_elements_column_uniq is | |
'A trigger function for AFTER INSERT OR UPDATE trigger that checks if all elements ' | |
'of the specified array column are unique across the table. If duplicate elements are ' | |
'are found, an exception with ERRCODE "unique_violation" is raised.' | |
'This function does not check for duplicates inside an array (in a row), just between ' | |
'the arrays in the column.' | |
'The column name to check must be passed as the first and only argument of the function.'; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment