当我们创建一个涉及到很多具有外键约束、视图、触发器、函数等的表的复杂数据库结构时,我们隐式地创建了一张对象之间的依赖关系网。例如,具有一个外键约束的表依赖于它所引用的表。
为了保证整个数据库结构的完整性,PostgreSQL确保我们无法删除仍然被其他对象依赖的对象。例如,尝试删除Section 5.3.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。实际上,没有数据库系统强制执行这条规则,但不同系统的默认行为是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;
(关于 SQL 语言函数的说明,请参阅Section 37.4。)PostgreSQL会知道get_color_note函数依赖于rainbow类型:删除该类型将迫使系统删除函数,因为它的参数类型将不再有定义。但是,PostgreSQL不会认为get_color_note依赖于my_colors表,因此不会在删除该表时删除函数。这种做法有缺点,也有好处。即使表不存在,函数在某种意义上仍然有效,尽管执行它会报错;创建一个同名新表后,函数就可以重新工作。