refint. Функции для реализации ссылочной целостности
В исходном дистрибутиве установлено по умолчанию: нет.
Связанные компоненты: отсутствуют.
Схема размещения:
ext.
Функции для реализации ссылочной целостности применяются для проверки ограничений внешних ключей:
-
Функция
check_primary_key()проверяет ссылающуюся таблицу.Для использования функции необходимо:
- создать триггер
BEFORE INSERT OR UPDATEс этой функцией для таблицы, ссылающейся на другую; - указать в аргументах триггера:
- имена столбцов ссылающейся таблицы, образующих внешний ключ;
- имя целевой таблицы;
- имена столбцов в целевой таблице, образующих первичный/уникальный ключ;
- для контроля нескольких внешних ключей необходимо создать триггер для каждой такой ссылки.
- создать триггер
-
Функция
check_foreign_key()проверяет целевую таблицу.Для использования функции необходимо:
- создать триггер
BEFORE DELETE OR UPDATEс этой функцией для таблицы, на которую ссылаются другие; - указать в аргументах триггера:
- число ссылающихся таблиц, для которых функция должна выполнить проверки;
- действие в случае обнаружения ссылающегося ключа:
cascade— удалить ссылающуюся строку;restrict— прервать транзакцию;setnull— установить в ссылающихся полях значенияNULL;
- имена столбцов целевой таблицы, образующих первичный/уникальный ключ;
- имена таблиц и столбцов в количестве, задаваемом первым аргументом, поля первичных/уникальных столбцов должны иметь пометку
NOT NULLи по ним должен быть создан уникальный индекс.
- создать триггер
Функциональность модуля вытеснена встроенным механизмом внешних ключей, но этот модуль все еще полезен в качестве примера.
Функция refint входит в модуль spi, который предоставляет несколько рабочих примеров использования «Интерфейса программирования сервера» (Server Programming Interface, SPI) и триггеров. Эти функции полезны как сами по себе и как заготовки, которые можно приспособить под собственные нужды.
Каждая группа функций представлена в виде отдельно устанавливаемого расширения:
refint. Функции для реализации ссылочной целостности;- autoinc. Функции для автоувеличения полей;
- insert_username. Отслеживание вносящего изменения пользователя;
- moddatetime. Функции для отслеживания времени последнего изменения.
Функции могут работать с любой таблицей, но при создании триггера необходимо явно указывать имена таблицы и полей.
Доработка
Не проводилась.
Установка
При наличии прав администратора СУБД включение модуля выполняется запросом:
CREATE EXTENSION refint SCHEMA ext;
Настройка
Не требуется.
Использование модуля
-
Создать таблицу
aс первичным ключомid:CREATE TABLE a (id int4 not null);CREATE UNIQUE INDEX ai ON a (id); -
Создать таблицы
bиc. Столбцыrefbтаблицыbи refc таблицыcявляются внешними ключами, ссылающимися наidтаблицыa:CREATE TABLE b (refb int4);CREATE INDEX bi ON b (refb);CREATE TABLE c (refc int4);CREATE INDEX ci ON c (refc); -
Создать триггер для таблицы
a:CREATE TRIGGER at BEFORE DELETE OR UPDATE ON a FOR EACH ROWEXECUTE PROCEDUREcheck_foreign_key (2,'cascade','id','b','refb','c','refc');где:
2- означает, что проверка должна быть выполнена для внешних ключей двух таблиц;- 'cascade' - определяет, что соответствующие ключи должны быть удалены;
id- имя столбца первичного ключа в инициируемой таблицеa, можно использовать необходимое количество столбцов;b- имя первой таблицы с внешними ключами;refb- имя столбца внешнего ключа в таблицеb, можно использовать необходимое количество столбцов, но количество ключевых столбцов в ссылках таблицыaдолжно быть таким же;c- имя второй таблицы с внешними ключами;refc- имя столбца внешнего ключа в таблицеb.
В итоге создана следующая структура таблицы
a:Table "ext.a"Column | Type | Collation | Nullable | Default--------+---------+-----------+----------+---------id | integer | | not null |Indexes:"ai" UNIQUE, btree (id)Triggers:at BEFORE DELETE OR UPDATE ON a FOR EACH ROW EXECUTE FUNCTION check_foreign_key('2', 'cascade', 'id', 'b', 'refb', 'c', 'refc') -
Создать триггер для таблицы
b:CREATE TRIGGER bt BEFORE INSERT OR UPDATE ON b FOR EACH ROWEXECUTE PROCEDUREcheck_primary_key ('refb','a','id');где:
refb- имя столбца внешнего ключа в таблице с инициализацией (b), можно использовать необходимое количество столбцов, но количество ключевых столбцов в ссылках таблицы должно быть таким же;A- имя таблицы, на которую указывает ссылка;id- имя столбца первичного ключа в таблице, на которую указывает ссылка.
В итоге создана следующая структура таблицы
b:Table "ext.b"Column | Type | Collation | Nullable | Default--------+---------+-----------+----------+---------refb | integer | | |Indexes:"bi" btree (refb)Triggers:bt BEFORE INSERT OR UPDATE ON b FOR EACH ROW EXECUTE FUNCTION check_primary_key('refb', 'a', 'id') -
Создать триггер для таблицы
c:CREATE TRIGGER ct BEFORE INSERT OR UPDATE ON c FOR EACH ROWEXECUTE PROCEDUREcheck_primary_key ('refc','a','id');где:
refc- имя столбца внешнего ключа в таблице с инициализацией (c), можно использовать необходимое количество столбцов, но количество ключевых столбцов в ссылках таблицы должно быть таким же;A- имя таблицы, на которую указывает ссылка;id- имя столбца первичного ключа в таблице, на которую указывает ссылка.
В итоге создана следующая структура таблицы
c:Table "ext.c"Column | Type | Collation | Nullable | Default--------+---------+-----------+----------+---------refc | integer | | |Indexes:"ci" btree (refc)Triggers:ct BEFORE INSERT OR UPDATE ON c FOR EACH ROW EXECUTE FUNCTION check_primary_key('refc', 'a', 'id') -
Вставить данные и выполнить проверку:
INSERT INTO a VALUES(10),(20),(30),(40),(50),(60);Вставить в таблицу
bнедопустимые данные и получить ошибку:INSERT INTO b VALUES (1); -- недопустимая ссылкаПример ошибки выполнения запроса:
ERROR: tuple references non-existent keyDETAIL: Trigger "bt" found tuple referencing non-existent key in "a".Вставить в таблицу
bкорректные данные с успешным завершением:INSERT INTO b VALUES(10),(30),(30); -- существующие ссылкиПример результата успешного выполнения запроса:
INSERT 0 3Вставить в таблицу
cнедопустимые данные и получить ошибку:INSERT INTO c VALUES (11); -- недопустимая ссылкаПример результата выполнения запроса:
ERROR: tuple references non-existent keyDETAIL: Trigger "ct" found tuple referencing non-existent key in "a".Вставить в таблицу
cкорректные данные с успешным завершением:INSERT INTO c VALUES(20),(20),(30); -- существующие ссылкиПример результата успешного выполнения запроса:
INSERT 0 3Извлечь данные из таблиц
a,b,c:SELECT * FROM a;SELECT * FROM b;SELECT * FROM c;Пример результата выполнения запроса:
id----102030405060(6 rows)refb------103030(3 rows)refc------202030(3 rows)Удаление строк:
DELETE FROM a WHERE id = 10;DELETE FROM a WHERE id = 20;DELETE FROM a WHERE id = 30;Пример результата выполнения запроса:
NOTICE: at: 1 tuple(s) of b are deletedNOTICE: at: 0 tuple(s) of c are deletedDELETE 1NOTICE: at: 0 tuple(s) of b are deletedNOTICE: at: 2 tuple(s) of c are deletedDELETE 1NOTICE: at: 2 tuple(s) of b are deletedNOTICE: at: 1 tuple(s) of c are deletedDELETE 1Извлечь данные из таблиц
a,b,c:SELECT * FROM a;SELECT * FROM b;SELECT * FROM c;Пример результата выполнения запроса:
id----405060(3 rows)refb------(0 rows)refc------(0 rows)
Ссылки на документацию разработчика
Дополнительно поставляемый модуль refint: https://www.postgresql.org/docs/15/contrib-spi.html#id-1.11.7.50.5.