跳转到内容
搜索文档

定义外键

最后更新 查看 MarkdownAgent 设置

D1 支持在数据库的表之间定义和强制执行外键约束。

外键约束允许您强制执行表之间的关系。例如,您可以使用外键在 users 表的 user_idorders 表的 user_id 之间创建严格绑定,这样就不能为不存在的用户创建订单。

外键约束还可以防止您删除被其他表中的行引用的行。例如,当 orders 表中的行引用 users 表中的行时,删除 users 表中的行。

默认情况下,D1 强制执行外键约束在所有查询和迁移中有效。这与在每个事务中设置 PRAGMA foreign_keys = on 的 SQLite 行为相同。

延迟外键约束

在对 D1 数据库运行查询迁移导入数据时,可能需要在创建表或更改 schema 期间临时禁用外键验证。

D1 的外键强制执行等同于 SQLite 的 PRAGMA foreign_keys = on 指令。由于 D1 在隐式事务中运行每个查询,用户查询无法在查询或迁移期间更改此设置。

相反,D1 允许您调用 PRAGMA defer_foreign_keys = onoff,这允许您临时违反外键约束(直到当前事务结束)。

调用 PRAGMA defer_foreign_keys = off 不会禁用当前事务之外的外键强制执行。如果您在事务结束时未解决未完成的外键违规,将失败并返回 FOREIGN KEY constraint failed 错误。

要延迟外键强制执行,在事务开始时或在会进行违规更改之前设置 PRAGMA defer_foreign_keys = on

-- Defer foreign key enforcement in this transaction.
PRAGMA defer_foreign_keys = on

-- Run your CREATE TABLE or ALTER TABLE / COLUMN statements
ALTER TABLE users ...

-- This is implicit if not set by the end of the transaction.
PRAGMA defer_foreign_keys = off

您也可以在解决未完成的外键约束后立即显式设置 PRAGMA defer_foreign_keys = off。如果仍有未完成的外键约束,您将收到 FOREIGN KEY constraint failed 错误,需要解决违规。

定义外键关系

外键关系可以在通过 CREATE TABLE 创建表时定义,或在通过 ALTER TABLE 语句向现有表添加列时定义。

以基于电子商务网站的两表示例说明:

  • 一个 users 表,定义用户账户的常见属性,包括唯一的 user_id 标识符。
  • 一个 orders 表,将订单映射回用户表中的 user_id

此映射定义为 FOREIGN KEY,确保:

  • 您不能从 users 表删除会违反外键约束的行。这意味着您不会最终出现没有有效用户可映射的订单。
  • orders 始终针对有效的 user_id 定义,降低创建引用无效(或不存在)用户的订单的风险。
CREATE TABLE users (
    user_id INTEGER PRIMARY KEY,
    email_address TEXT,
    name TEXT,
    metadata TEXT
)

CREATE TABLE orders (
    order_id INTEGER PRIMARY KEY,
    status INTEGER,
    item_desc TEXT,
    shipped_date INTEGER,
    user_who_ordered INTEGER,
    FOREIGN KEY(user_who_ordered) REFERENCES users(user_id)
)

每个表可以定义多个外键关系,外键定义可以引用整个数据库 schema 中的多个表。

外键操作

您可以在外键定义中定义操作,以限制或传播对父行(REFERENCES table(column))的更改。定义操作使在应用中使用外键约束更容易理解和推理,并帮助清理相关数据或防止数据孤立。

定义 ON UPDATE 和/或 ON DELETE 子句作为外键关系的一部分时,可以设置五种操作。根据需求,可以为 ON UPDATEON DELETE 定义不同的操作。

  • CASCADE - 更新或删除父键时,删除所有关联的子键(行)。
  • RESTRICT - 当任何子键引用父键时,不能更新或删除父键。与默认外键强制执行不同,应用了 RESTRICT 的关系立即返回错误,而不是在事务结束时。
  • SET DEFAULT - 将外键定义引用的子列设置为 schema 中定义的 DEFAULT 值。如果子列未设置 DEFAULT,则不能使用此操作。
  • SET NULL - 将外键定义引用的子列设置为 SQL NULL
  • NO ACTION - 不采取任何操作。

在以下示例中,从 users 表删除用户将删除 scores 表中的所有相关行,因为您定义了 ON DELETE CASCADE。如果您不想完全保留已删除用户的分数,请删除 scores 表中的所有相关行。这可能意味着其他用户无法再查找或引用仍然有效的分数。

CREATE TABLE users (
    user_id INTEGER PRIMARY KEY,
    email_address TEXT,
)

CREATE TABLE scores (
    score_id INTEGER PRIMARY KEY,
    game TEXT,
    score INTEGER,
    player_id INTEGER,
    FOREIGN KEY(player_id) REFERENCES users(user_id) ON DELETE CASCADE
)

后续步骤

这篇文档对您有帮助吗?