SQL:通过外键指定唯一约束并高效查询
SQL: Specifying a unique constraint through a foreign key and efficiently querying it
架构
我在 MySQL 中有以下数据库模式:
主题
- id: PK
- 名称:字符串,唯一
- slug:字符串,唯一
例如(5, Algebra, algebra), (6, Java, java) ...
module_sections
- id: PK
- topic_id: FK => topics.id
- 名称:字符串
- 顺序:无符号整数,索引
- 独一无二([topic_id, 名字])
例如
(1, 5, Algebra Basics, 1),
(2, 6, Introduction to Programming, 1),
(3, 6, Variables, 2) ...
模块
- id: PK
- module_section_id: FK => module_sections.id
- 名称:字符串
- slug: 字符串
顺序:无符号整数,索引
独一无二([module_section_id, 名字])
- !问题:唯一([module_section.topic_id,鼻涕虫])
例如
(1, 1, Collecting like terms, collecting-like-terms, 1),
(2, 2, What is Programming?, what-is-programming, 1),
(3, 2, Installing Java, installing-java, 2) ...
数据库模式解释
上述数据库显示 3 tables。每个topic
有很多module_sections
,每个module_sections
有很多modules
。
上面的示例数据可以写成这样的列表:
- 代数
- 代数基础知识
- 收集喜欢的条款
- Java
- 编程简介
- 什么是编程?
- 正在安装Java
- 变量
每个 topic
在 table.
中必须有唯一的 name
和 slug
每个 module section
必须有一个唯一的 name
topic
。 (例如,我们可以在 Algebra
和 Java
中都有一个名为 Introduction
的部分,因为它们都是不同的主题)
每个 module
对于那个 topic
必须是唯一的(不仅仅是那个部分)。例如,我们不能在 Introduction to Programming
和 Variables
下同时包含模块 What is Programming?
(因为它们都在同一主题中),但我们可以在 [=33] 下包含 Arithmetic
=] 和 Introduction to Programming
(因为它们在不同的主题中)。不幸的是,我无法在架构中指定此特定约束。
查询
我希望高效地执行以下查询:
- 通过鼻涕虫获得
topic
(我设法做到了)
通过正确排序的主题 slug 列出特定 topic
的所有 module sections
和 modules
(我设法做到了)
正在使用 topic slug
和 module slug
检索模块。例如:如果主题 slug 是 "java" 并且模块 slug 是 "installing-java" 它应该 return modules
中 PK 3 的记录。 (我不知道如何有效地做到这一点)
问题
总结一下,我面临的问题如下:
- 如何指定完整性约束:
unique([module_section.topic_id, slug])
在modules
table.
- 使用
topic slug
和 module slug
检索模块
随时提出对模式的更改建议:
- 保持完整性约束
- 可以高效地执行查询
我正在为 PHP 框架使用 Laravel。
How to specify the integrity constraint: unique([module_section.topic_id, slug]) in the modules table.
你不能。 SQL 不支持诸如此类的间接约束。您只能限制直接出现在约束适用的 table 中的值。
您的问题源于您选择使用单列代理键,再加上您对 slug 唯一性的要求与您对模块唯一性的要求不一致。使用这样的结构,无法表达您想放置的 SQL 约束。作为替代方案,您可以在 module
table 上创建插入和更新触发器,以在模块 slugs 上强制执行所需条件。
另一方面,如果 module_section
的 PK 是复合的,并且 topic_id
作为其列之一,您可以编写一个约束,就像您想象的那样。然后 module
中引用模块部分的 FK 将在其中包含主题 ID,您可以使用约束来实现您想要的。
架构
我在 MySQL 中有以下数据库模式:
主题
- id: PK
- 名称:字符串,唯一
- slug:字符串,唯一
例如(5, Algebra, algebra), (6, Java, java) ...
module_sections
- id: PK
- topic_id: FK => topics.id
- 名称:字符串
- 顺序:无符号整数,索引
- 独一无二([topic_id, 名字])
例如
(1, 5, Algebra Basics, 1),
(2, 6, Introduction to Programming, 1),
(3, 6, Variables, 2) ...
模块
- id: PK
- module_section_id: FK => module_sections.id
- 名称:字符串
- slug: 字符串
顺序:无符号整数,索引
独一无二([module_section_id, 名字])
- !问题:唯一([module_section.topic_id,鼻涕虫])
例如
(1, 1, Collecting like terms, collecting-like-terms, 1),
(2, 2, What is Programming?, what-is-programming, 1),
(3, 2, Installing Java, installing-java, 2) ...
数据库模式解释
上述数据库显示 3 tables。每个topic
有很多module_sections
,每个module_sections
有很多modules
。
上面的示例数据可以写成这样的列表:
- 代数
- 代数基础知识
- 收集喜欢的条款
- 代数基础知识
- Java
- 编程简介
- 什么是编程?
- 正在安装Java
- 变量
- 编程简介
每个 topic
在 table.
name
和 slug
每个 module section
必须有一个唯一的 name
topic
。 (例如,我们可以在 Algebra
和 Java
中都有一个名为 Introduction
的部分,因为它们都是不同的主题)
每个 module
对于那个 topic
必须是唯一的(不仅仅是那个部分)。例如,我们不能在 Introduction to Programming
和 Variables
下同时包含模块 What is Programming?
(因为它们都在同一主题中),但我们可以在 [=33] 下包含 Arithmetic
=] 和 Introduction to Programming
(因为它们在不同的主题中)。不幸的是,我无法在架构中指定此特定约束。
查询
我希望高效地执行以下查询:
- 通过鼻涕虫获得
topic
(我设法做到了) 通过正确排序的主题 slug 列出特定
topic
的所有module sections
和modules
(我设法做到了)正在使用
topic slug
和module slug
检索模块。例如:如果主题 slug 是 "java" 并且模块 slug 是 "installing-java" 它应该 returnmodules
中 PK 3 的记录。 (我不知道如何有效地做到这一点)
问题
总结一下,我面临的问题如下:
- 如何指定完整性约束:
unique([module_section.topic_id, slug])
在modules
table. - 使用
topic slug
和module slug
检索模块
随时提出对模式的更改建议:
- 保持完整性约束
- 可以高效地执行查询
我正在为 PHP 框架使用 Laravel。
How to specify the integrity constraint: unique([module_section.topic_id, slug]) in the modules table.
你不能。 SQL 不支持诸如此类的间接约束。您只能限制直接出现在约束适用的 table 中的值。
您的问题源于您选择使用单列代理键,再加上您对 slug 唯一性的要求与您对模块唯一性的要求不一致。使用这样的结构,无法表达您想放置的 SQL 约束。作为替代方案,您可以在 module
table 上创建插入和更新触发器,以在模块 slugs 上强制执行所需条件。
另一方面,如果 module_section
的 PK 是复合的,并且 topic_id
作为其列之一,您可以编写一个约束,就像您想象的那样。然后 module
中引用模块部分的 FK 将在其中包含主题 ID,您可以使用约束来实现您想要的。