Skip to content

5.14. 依赖项跟踪#

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

为了确保整个数据库结构的完整性,PostgreSQL确保您不能删除其他对象仍依赖的对象。例如,尝试删除我们在第 5.4.5 节中考虑的 products 表,而 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输出。)

PostgreSQL中几乎所有DROP命令都支持指定CASCADE。当然,可能依赖项的性质会因对象类型而异。您还可以编写RESTRICT而不是CASCADE来获取默认行为,即防止删除任何其他对象依赖的对象。

注意

根据 SQL 标准,在DROP命令中需要指定RESTRICTCASCADE。没有数据库系统实际执行该规则,但默认行为是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;

那么DROP将知道该函数对my_colors表的依赖关系并强制执行该依赖关系。