Ste*_*ven 8 normalization database-design constraint
在许多一对多(数据模型)维基百科的文章使用作者和图书的例子:
例如,将 A 视为作者,将 B 视为书籍。一个作者可以写几本书,一本书可以由几个作者写。
在关系数据库管理系统中,这种关系通常是通过关联表(也称为交叉引用表)来实现的,例如,AB 具有两个一对多关系 A -> AB 和 B -> AB。在这种情况下,AB 的逻辑主键由两个外键(即 A 和 B 的主键的副本)形成。
有了约束,你会如何执行一本书必须有至少一个作者?
笔记:
如何在 SQL 中仅使用 DDL(FOREIGN KEY和UNIQUE约束)执行此操作:
CREATE TABLE author
( author_id INT NOT NULL,
author_name VARCHAR(100),
CONSTRAINT author_pk
PRIMARY KEY (author_id)
) ;
CREATE TABLE book
( book_id INT NOT NULL,
book_title VARCHAR(100),
CONSTRAINT book_pk
PRIMARY KEY (book_id)
) ;
CREATE TABLE book_author
( book_id INT NOT NULL,
author_id INT NOT NULL,
CONSTRAINT book_author_pk
PRIMARY KEY (book_id, author_id),
CONSTRAINT book__book_author_fk
FOREIGN KEY (book_id) REFERENCES book (book_id),
CONSTRAINT author__book_author_fk
FOREIGN KEY (author_id) REFERENCES author (author_id)
) ;
Run Code Online (Sandbox Code Playgroud)
到目前为止,这仅实现了书籍和作者之间常见的多对多关系。这意味着一本书可以有 0 个、1 个或多个作者,一个作者可以有 0 个、1 个或多个书籍。
如果我们想要严格的“一本书必须至少有1 位作者”,我们可以添加另一列book和附加约束:
ALTER TABLE book
ADD COLUMN author_id INT NOT NULL,
ADD CONSTRAINT book_must_have_at_least_1_author_fk
FOREIGN KEY (book_id, author_id)
REFERENCES book_author (book_id, author_id) ;
Run Code Online (Sandbox Code Playgroud)
笔记:
为了使上述约束发挥作用,我们需要一个已实现可延迟约束的 DBMS(例如 Postgres、Oracle),或者可以在一个语句中向多个表插入/删除(Postgres)。如果没有这些,我们可以放宽一些限制,例如分三步解除NOT NULLfrom和插入(比如一本新书):book (author_id)
然后,我们可以将上述步骤包装在事务/过程中,然后仅通过这些事务/过程限制对表的访问(每个操作一个过程,插入新书及其作者,删除书籍及其作者,更新作者,删除作者)来自书本等)。
如果不是完全明显,这些过程可能会变得有点复杂,例如,当必须删除一本书的“主要”作者时,因为该过程必须搜索其余作者并相应更新,book.author_id或者如果没有,则失败/拒绝删除其他作者离开了。
另一个选择 - 因为我们提到了过程 - 是从一开始就将它们用于所有插入/更新/删除操作。如果设计和测试正确,它们可以强制执行所有约束,允许不声明任何外键。