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
命令中需要指定RESTRICT
或CASCADE
。没有数据库系统实际执行该规则,但默认行为是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
表的依赖关系并强制执行该依赖关系。