Skip to content

外键与级联 ​

在 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);
  • 避免循环依赖:在某些复杂的关系中,可能会产生循环外键依赖,导致插入和删除操作产生问题。要避免设计中出现循环依赖。

小结 ​

外键约束和级联操作是关系型数据库中非常重要的数据完整性工具。外键用于确保表之间的数据一致性,而级联操作则可以自动处理父表数据变化对子表数据的影响。在设计数据库时合理使用外键和级联操作,可以减少数据不一致和维护复杂度。

外键与级联 ​

在 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);
  • 避免循环依赖:在某些复杂的关系中,可能会产生循环外键依赖,导致插入和删除操作产生问题。要避免设计中出现循环依赖。

小结 ​

外键约束和级联操作是关系型数据库中非常重要的数据完整性工具。外键用于确保表之间的数据一致性,而级联操作则可以自动处理父表数据变化对子表数据的影响。在设计数据库时合理使用外键和级联操作,可以减少数据不一致和维护复杂度。

Released under the MIT License.