我正在尝试实现一个列表。每个列表项将与一个或多个标签相关联。每个标签将与一个或多个列表项相关联。
我对这个领域还是很陌生。幸运的是,我设法在这个问题中找到了一个解决方案,其答案表明了以下数据库设计:
Articles table
- id
- name
- etc
Relational Tag Arts table
- Fkey tags id
- Fkey article id
Tags table
- id
- name
- etc
Run Code Online (Sandbox Code Playgroud)
我已经创建了我的三个表。现在我不明白的是,引用表(包含两个外键的表)是否应该具有主键、自动增量或索引?
[已解决]虽然我不是 100% 确定,但我猜参考表的内容是故意“重复”的。例如,如果我添加一个与 5 个标签相关联的新项目,那么引用表应该再添加 5 个记录,这些记录都具有相同的项目 ID,但具有不同的标签 ID。我对么?
您可能需要考虑退后一步来考虑设计过程。一旦你熟悉了,你通常可以跳过它并直接实现它。我建议从表格开始(理论上称为关系)。你似乎发现了:
* Articles
* Tags
Run Code Online (Sandbox Code Playgroud)
下一步是考虑是什么唯一标识了文章和标签中的行(元组)。这可能是单个列(属性)或列的组合。如果你和某人谈论过一篇文章,你会用什么来识别它?所有这些属性或属性组合都称为候选键。在这个过程中,你可能会选择添加一个人工(代理)键,我假设id
就是这样一个属性。例如,添加代理键的原因可能是自然键太复杂、不够稳定等。但您仍应将它们声明为 UNIQUE。
说到 id,我强烈建议您将其命名为 article_id 或类似名称,并通过模型坚持使用该名称。诸如 Id、Name 等名称太模糊而没有意义,并且通常会与您使用的 DBMS 中的保留字相冲突。假设我们已经得出结论:
CREATE TABLE Articles
( article_id ... not null
, article_name ... not null
, publishing_date date not null
, ...
, primary key (article_id) -- surrogate key
, unique ( article_name, publishing_date ) -- natural key
);
CREATE TABLE Tags
( tag_id ... not null primary key
, tag_name ... not null unique
);
Run Code Online (Sandbox Code Playgroud)
这些表是如何关联的?您似乎已经得出结论,文章和标签之间存在 NN 关系,这通常是通过第三个表(有时称为连接或链接表)来实现的。我们称这个表为:
CREATE TABLE Article_Tags
( article_id ... not null references Articles (article_id)
, tag_id ... not null references Tags (tag_id)
);
Run Code Online (Sandbox Code Playgroud)
现在对于您最初的问题,是什么唯一地标识了这种关系?我会在这里建议一个复合键,如:
CREATE TABLE Article_Tags
( article_id ... not null references Articles (article_id)
, tag_id ... not null references Tags (tag_id)
, primary key (article_id, tag_id)
);
Run Code Online (Sandbox Code Playgroud)
并且不添加额外的代理键(我什至不确定这种键的用途是什么,但我经常看到它以某种design by blindfold
方式添加)。使用建议的组合键,您可以保证对于每篇文章不会多次使用相同的标签。
如果您有时想检索给定标签的所有文章,您可以添加如下索引:
CREATE UNIQUE INDEX ... ON Article_Tags (tag_id, article_id);
Run Code Online (Sandbox Code Playgroud)
编辑:关于索引与键的一些信息
索引是一个物理概念,实际上在 SQL 标准中甚至都没有提到,这意味着每个供应商都可以随心所欲地实现它们,而某种类型的键是一个逻辑概念。请注意,在某些 DBMS 中,这两个概念之间存在模糊的界限,例如,可能有外键引用 SQL-server 中的唯一索引,而 MySQL 调用索引键。
大多数 DBMS:s(以及我认识的每个人)都使用物理索引实现逻辑键(UNIQUE、PRIMARY KEY),因此如果您添加一个键,就会在幕后创建一个索引。以下键是多余的:
PRIMARY KEY (a,b) <=> UNIQUE (b,a)
Run Code Online (Sandbox Code Playgroud)
因为如果 (a,b) 是唯一的,那么 (b,a) 也是唯一的。如果存在另一个,那么您的 DBMS 将不允许您创建一个,这是一个很大的机会。另一方面:
INDEX (a,b) is not redundant with INDEX(b,a)
Run Code Online (Sandbox Code Playgroud)
由于查询如下:
SELECT ... FROM T WHERE a = ?
Run Code Online (Sandbox Code Playgroud)
可以使用第一个索引有效地找到匹配的行,但第二个索引不能。你可以把它想象成你有一个按名字、姓氏组织的索引,你试图找到一个姓盖茨或托瓦尔兹的人。在找到所有具有这些姓氏的人之前,您基本上必须浏览许多名字。
那么为什么不为搜索中使用的每一列创建一个单列索引呢?许多 DBMS 可以执行 INDEX ANDING(但有些不能),但无论如何它比使用一个多列索引效率低。再一次,您可以将其与首先查看 first-name 的索引并发现第 14、50 和 126 页上有一个 Bill 的过程进行比较。然后查看 last-name 的另一个索引并发现有一个 Bill盖茨在第 21、50、123 和 212 页,最后将这两个集合相交得出比尔盖茨可以在第 50 页找到的结论。非常简单地。
您可以使用多列索引 a,b,c,d,e,f 来查找 a、ab、abc 等,但是如果您查找 WHERE d=? 和 f=?。
上面的内容非常简单,但可能会给你一两个关于如何开始思考设计过程的想法。
归档时间: |
|
查看次数: |
372 次 |
最近记录: |