Postgresql 中文操作指南
5.14. Dependency Tracking #
当涉及许多具有外键约束、视图、触发器、函数等的表的复杂数据库结构时,将隐式创建对象之间的依赖网络。例如,具有外键约束的表依赖于它引用的表。
为了确保整个数据库结构的完整性,PostgreSQL 确保你无法删除其他对象仍然依赖的对象。例如,尝试删除我们考虑在 Section 5.4.5 中的产品表,该表依赖于订单表,这将导致出现类似以下内容的错误消息:
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;
以及所有依赖对象都将被删除,依赖于它们的任何对象也会递归地被删除。在这种情况下,它不会删除订单表,它只会删除外键约束。它在那里停止是因为没有任何内容依赖于外键约束。(如果你想检查 DROP … CASCADE 将做什么,请在没有 CASCADE 的情况下运行 DROP,并读取 DETAIL 输出。)
PostgreSQL 中几乎所有 DROP 命令都支持指定 CASCADE。当然,可能的依赖项的性质会因对象类型而异。你还可以编写 RESTRICT 而不是 CASCADE,以获取默认行为,即阻止删除任何其他对象依赖的对象。
Note
根据 SQL 标准,DROP 命令中需要指定 RESTRICT 或 CASCADE。没有任何数据库系统实际执行此规则,但默认行为是 RESTRICT 还是 CASCADE 则因系统而异。
如果 DROP 命令列出了多个对象,则仅当组外存在依赖项时才需要 CASCADE。例如,在说明 DROP TABLE tab1, tab2 中,外键引用 tab1 从 tab2 的存在并不意味着需要 CASCADE 才能成功。
对于将主体定义为字符串文字的用户定义函数或过程,PostgreSQL 会跟踪与函数外部可见属性(如其参数和结果类型)关联的依赖项,但 not 依赖项只能通过检查函数主体得知。以这种情况为例:
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;
(请参阅 Section 38.5 了解 SQL 语言函数的说明。)PostgreSQL 将意识到 get_color_note 函数依赖于 rainbow 类型:删除该类型将强制删除该函数,因为其参数类型将不再被定义。但 PostgreSQL 不会认为 get_color_note 依赖于 my_colors 表,因此不会在删除表的时候删除该函数。尽管这种方法有一些缺点,但也有好处。从某种意义上说,即使表丢失了,函数仍然有效,尽管执行它会导致错误;创建具有相同名称的新表将允许函数再次工作。
另一方面,对于主体以 SQL 标准样式编写的 SQL 语言函数或过程,解析器在函数定义时解析主体,并存储解析器识别的所有依赖关系。因此,如果我们以以下方式编写上述函数:
CREATE FUNCTION get_color_note (rainbow) RETURNS text
BEGIN ATOMIC
SELECT note FROM my_colors WHERE color = $1;
END;
那么 DROP 将了解和强制执行函数对 my_colors 表的依赖性。