↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3

5.14. 依赖跟踪 #

当我们创建涉及许多带外键约束的表、视图、触发器、函数等对象的复杂数据库结构时,我们隐式地创建了一张对象之间的依赖关系网。例如,具有一个外键约束的表依赖于它所引用的表。

为了保证整个数据库结构的完整性,PostgreSQL 确保我们无法删除仍然被其他对象依赖的对象。例如,尝试删除第 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,从而得到默认行为,也就是阻止删除任何仍被其他对象依赖的对象。

注意

根据 SQL 标准,在 DROP 命令中指定 RESTRICT 或 CASCADE 是被要求的。但没有哪个数据库系统真正强制了这个规则,但是不同的系统中两种默认行为都是可能的。

如果一个 DROP 命令列出了多个对象,只有在存在指定对象构成的组之外的依赖关系时才需要 CASCADE。例如,如果发出命令 DROP TABLE tab1, tab2 且存在从 tab2 到 tab1 的外键引用,那么就不需要 CASCADE 即可成功执行。

对于一个将其主体定义为字符串字面量的用户定义函数或过程,PostgreSQL 会跟踪与函数的外部可见属性相关的依赖关系,例如其参数和结果类型,但不会跟踪只有通过检查函数主体才能知道的依赖关系。例如,考虑以下情况:

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;

(请参阅第 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;

那么函数对 my_colors 表的依赖关系将被知晓,并由 DROP 强制执行。

报告文档问题

阅读 上游文档. 通过 PostgreSQL 文档反馈表单.