5.14. Отслеживание зависимостей#
5.14. Отслеживание зависимостей #
Когда вы создаете сложные структуры баз данных, включающие множество таблиц с ограничениями внешнего ключа, представлениями, триггерами, функциями и т. д., вы неявно создаете сеть зависимостей между объектами. Например, таблица с ограничением внешнего ключа зависит от таблицы, на которую она ссылается.
Для обеспечения целостности всей структуры базы данных, Tantor BE гарантирует, что вы не можете удалить объекты, от которых зависят другие объекты. Например, попытка удалить таблицу products, рассмотренную в Раздел 5.4.5, при условии, что от нее зависит таблица orders, приведет к появлению сообщения об ошибке, типа этой:
DROP TABLE products; ERROR: cannot drop table products because other objects depend on it DETAIL: constraint orders_product_no_fkey on table orders depends on table products HINT: Use DROP ... CASCADE to drop the dependent objects too.
Сообщение об ошибке содержит полезную подсказку: если вы не хотите заморачиваться с удалением всех зависимых объектов по отдельности, вы можете выполнить:
DROP TABLE products CASCADE;
и рекурсивно будут удалены все зависимые объекты, а также все объекты, которые зависят от них. В этом случае таблица orders не удаляется, удаляется лишь ограничение внешнего ключа. Удаление не затронет другие объекты, так как никакие объекты не зависит от ограничения внешнего ключа. (Если нужно проверить, что произойдет при DROP ... CASCADE
, запустите DROP
без CASCADE
и прочитайте вывод DETAIL
).
Почти все команды DROP
в Tantor BE поддерживают указание CASCADE
. Конечно, характер возможных зависимостей зависит от типа объекта. Также можно написать RESTRICT
вместо CASCADE
, чтобы активировать поведение по умолчанию, которое заключается в предотвращении удаления объектов, от которых зависят другие объекты.
Примечание
Согласно стандарту SQL, в команде DROP
требуется указать либо RESTRICT
, либо CASCADE
. Ни одна система управления базами данных на самом деле не принуждает к соблюдению этого правила, но поведение по умолчанию может быть либо RESTRICT
, либо CASCADE
в зависимости от системы.
Если команда DROP
перечисляет несколько объектов, CASCADE
требуется только в случае наличия зависимостей вне указанной группы. Например, при использовании DROP TABLE tab1, tab2
наличие внешнего ключа, ссылающегося на tab1
из tab2
, для успешного выполнения не требуется указывать CASCADE
.
Для пользовательской функции или процедуры, тело которой определено как строковый литерал, Tantor BE отслеживает зависимости, связанные с внешними свойствами функции, такими как ее аргументы и типы результатов, но не зависимости, которые могут быть известны только при изучении тела функции. В качестве примера, рассмотрим следующую ситуацию:
CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple'); CREATE TABLE my_colors (color rainbow, note text); CREATE FUNCTION get_color_note (rainbow) RETURNS text AS 'SELECT note FROM my_colors WHERE color = $1' LANGUAGE SQL;
( Функции языка SQL описаны в Раздел 35.5). Tantor BE будет знать, что функция get_color_note
зависит от типа rainbow
: удаление типа приведет к удалению функции, потому что соответсвующий тип аргумента больше не будет определен. Но Tantor BE не будет считать, что функция get_color_note
зависит от таблицы my_colors
, и поэтому не удалит функцию, если таблица будет удалена. Несмотря на недостатки такого подхода, есть и определенные преимущества. Функция все еще будет действительна в некотором смысле, если таблица отсутствует, хотя ее выполнение вызовет ошибку; при создании новой таблицы с тем же именем функция снова будет работать.
С другой стороны, при определении функции или процедуры в стиле стандарта SQL её тело парсится, и сохраняются все зависимости, распознаваемые синтаксическим анализатором. Таким образом, если мы напишем функцию выше как
CREATE FUNCTION get_color_note (rainbow) RETURNS text BEGIN ATOMIC SELECT note FROM my_colors WHERE color = $1; END;
тогда зависимость функции от таблицы my_colors
будет известна и принудительно обработана командой DROP
.