主题
外键与级联
在 PostgreSQL 中,外键(Foreign Key)用于建立两个表之间的关系。外键约束可以确保数据的一致性和完整性,防止出现无效的数据行。级联操作(Cascade)是外键约束中的一个重要特性,用于定义当父表数据发生变化时,子表应采取的行为。
外键 (Foreign Key)
外键约束确保子表中的数据与父表中的数据一致。外键列中的每个值都必须引用父表中的某个有效值。
创建外键约束
在创建表时,可以使用 FOREIGN KEY
约束来定义外键。以下是一个例子,表示 orders
表中的 customer_id
列引用 customers
表中的 id
列:
sql
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
name VARCHAR(100)
);
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT,
amount DECIMAL,
FOREIGN KEY (customer_id) REFERENCES customers(id)
);
在这个例子中,orders
表中的 customer_id
列是外键,引用了 customers
表的 id
列。
外键约束的特性
- 数据一致性:外键约束确保子表的列值必须与父表中的数据一致。
- 删除与更新行为:外键约束可以定义在父表数据删除或更新时,子表应如何响应。
修改外键约束
如果需要修改外键约束,可以使用 ALTER TABLE
:
sql
ALTER TABLE orders
ADD CONSTRAINT fk_customer
FOREIGN KEY (customer_id) REFERENCES customers(id);
删除外键约束
可以使用以下命令删除外键约束:
sql
ALTER TABLE orders
DROP CONSTRAINT fk_customer;
级联操作 (Cascade)
级联操作定义了在父表数据发生变化时,子表应如何响应。常见的级联操作有:
- CASCADE:当父表的数据被删除或更新时,自动删除或更新子表中相关的数据。
- SET NULL:当父表的数据被删除或更新时,子表中的外键列将被设置为 NULL。
- SET DEFAULT:当父表的数据被删除或更新时,子表中的外键列将被设置为默认值。
- RESTRICT:当父表的数据被删除或更新时,如果子表中有相关数据,则操作将被拒绝。
- NO ACTION:当父表的数据被删除或更新时,不会对子表执行任何操作,实际上与 RESTRICT 类似,但是在检查约束时延迟执行。
创建带有级联操作的外键约束
可以在创建外键时指定级联操作。例如,以下定义了当 customers
表中的记录被删除时,自动删除 orders
表中的相关记录:
sql
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT,
amount DECIMAL,
FOREIGN KEY (customer_id) REFERENCES customers(id)
ON DELETE CASCADE
);
在这个例子中,ON DELETE CASCADE
表示当 customers
表中的记录被删除时,orders
表中所有关联的记录也会被删除。
级联操作的示例
CASCADE
sql
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT,
amount DECIMAL,
FOREIGN KEY (customer_id) REFERENCES customers(id)
ON DELETE CASCADE
);
当删除 customers
表中的某个客户时,所有与该客户相关的订单记录也会被删除。
SET NULL
sql
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT,
amount DECIMAL,
FOREIGN KEY (customer_id) REFERENCES customers(id)
ON DELETE SET NULL
);
当删除 customers
表中的某个客户时,所有与该客户相关的订单记录中的 customer_id
会被设置为 NULL
。
SET DEFAULT
sql
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT DEFAULT 1,
amount DECIMAL,
FOREIGN KEY (customer_id) REFERENCES customers(id)
ON DELETE SET DEFAULT
);
当删除 customers
表中的某个客户时,所有与该客户相关的订单记录中的 customer_id
会被设置为默认值 1
。
RESTRICT
sql
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT,
amount DECIMAL,
FOREIGN KEY (customer_id) REFERENCES customers(id)
ON DELETE RESTRICT
);
当试图删除 customers
表中的某个客户时,如果该客户有相关的订单记录,删除操作会被拒绝。
NO ACTION
sql
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT,
amount DECIMAL,
FOREIGN KEY (customer_id) REFERENCES customers(id)
ON DELETE NO ACTION
);
与 RESTRICT
类似,但 NO ACTION
会在稍后的检查阶段进行延迟检查。
外键约束的优化
- 使用索引:虽然 PostgreSQL 会为外键列自动创建索引,但如果外键列上没有索引,查询性能可能会下降。对于外键列,尤其是用于删除和更新的外键列,建议手动创建索引以提高性能。
sql
CREATE INDEX idx_orders_customer_id ON orders (customer_id);
- 避免循环依赖:在某些复杂的关系中,可能会产生循环外键依赖,导致插入和删除操作产生问题。要避免设计中出现循环依赖。
小结
外键约束和级联操作是关系型数据库中非常重要的数据完整性工具。外键用于确保表之间的数据一致性,而级联操作则可以自动处理父表数据变化对子表数据的影响。在设计数据库时合理使用外键和级联操作,可以减少数据不一致和维护复杂度。