【问题标题】:Normalising a tags table in a database for SQLite规范化 SQLite 数据库中的标签表
【发布时间】:2021-04-04 19:34:10
【问题描述】:

所以我正在学习如何使用 SQLite 创建数据库,并且我正在努力尝试用供应商标记和供应商标记名中的逗号分隔值分隔字符串,然后将标记号与标记名对齐。

让我们说每行的 vendorid 从 1,2,3... 等递增。 这是一个架构

CREATE TABLE unnormalized(
  vendor_tag varchar(200),
  vendor_tag_name varchar(200),
  vendor_id int
  );
  
 INSERT INTO unnormalized
VALUES
('5,8,30,24','Burgers,Desserts,Fries,Salads',1),
('5','Burgers',2),
('8,42','Desserts,Mexican',3),
('1,5,30,16','American,Burgers,Fries,Sandwiches',4),
('1,5,30,16','American,Burgers,Fries,Sandwiches',5);

【问题讨论】:

  • 改进您的问题 - 请向我们展示您目前的发现。你觉得餐桌的设计应该是怎样的?这使某人更容易插话您应该如何进一步进行(如果需要)。请记住,我们不是来为您免费工作的。不要担心犯错 - 没有人会不犯错误而学习。
  • 发布您拥有的相关表格的定义,而不仅仅是表格的 2 列。
  • use text, not images/links, for text--including tables & ERDs。转述或引用其他文本。只提供您需要的东西并将其与您的问题联系起来。仅将图像用于无法表达为文本或增强文本的内容。无法搜索或剪切和粘贴图像。在图片中包含图例/键和说明。
  • 请提出 1 个经过研究的特定非重复问题。 PS 现在,您只是要求我们用定制的教程重写教科书并完成您的(家庭)作业,而您没有表现出任何研究或其他努力。请参阅How to Ask,点击谷歌搜索“stackexchange 作业”和投票箭头鼠标悬停文本。按照教科书的理由展示你的工作步骤,并在你被卡住的第一个地方问一个具体的问题。引用您所依赖的定义、定理、算法和启发式方法。所有步骤也是常见问题解答。
  • “供应商从每行的 1,2,3... 等递增”是什么意思? “分离”和“对齐”是什么意思?你为什么说“正常化”?你想完成什么,从什么开始,在什么过程中产生什么?这还不清楚。使用足够多的单词、句子和对部分示例的引用来清楚完整地表达你的意思。在给出业务关系(船舶)/关联或表(基础或查询结果)时,说明其中的一行根据其列值说明了业务情况。另外:minimal reproducible example

标签: sql sqlite database-design many-to-many database-normalization


【解决方案1】:

图片中的列名不描述列内容。

首先,我要定义一个Vendor 表:

Vendor
------
VendorID
VendorName
...

其中VendorID 是一个自动递增的整数盲主(集群)键,VendorName 是供应商的名称。其他供应商属性将属于此表。

编辑添加:您的图片中没有任何供应商,所以让我们制作几个供应商。

Vendor table

VendorID | VendorName
-------- | ----------
       1 | McDonald's
       2 | IHOP

接下来,我将定义一个Tag 表。

Tag
---
TagID
TagName

其中TagID 是一个自动递增的整数盲主(集群)键,TagName 是标签的名称。

编辑添加:这是 Tag 表的内容。

Tag table

TagID | TagName
----- | -------
    1 | American
    2 | Arabic
    3 | ?
    4 | Breakfast
    5 | Burgers
  ...

每个标签都有一行。

最后,由于 Vendor 和 Tag 之间的关系是多对多的,我将定义一个VendorTag 联结表。

VendorTag
---------
VendorTagID
VendorID
TagID
Created Timestamp

其中VendorTagID 是自动递增整数盲主(集群)键,VendorID 是返回Vendor 表的外键,TagID 是返回Tag 表的外键.

您还可以在(VendorID, TagID) 上定义一个唯一索引,以便您可以相当轻松地检索供应商的标签。如果您还想检索标签的供应商,可以在 (TagID, VendorID) 上创建另一个唯一索引。

编辑添加:这是 VendorTag 表的某些行可能的样子。

VendorTag table

VendorTagID | VendorID | TagID | Created Timestamp
----------- | -------- | ----- | -------------------
          1 |        1 |     4 | 2020-12-27 16:44:10
          2 |        1 |     8 | 2020-12-27 16:44:10
          3 |        1 |    10 | 2020-12-27 16:44:11
          4 |        1 |    91 | 2020-12-27 16:44:11

每个表的每一列都包含一个且只有一个值。这是database normalization 的要点之一。数据库中没有重复信息是数据库规范化的另一个点。

【讨论】:

  • @HappyCamper:查看我的更新答案。在规范化数据库中,每一行的每一列都包含一个且只有一个值。
  • 谢谢!我的脑袋花了一段时间才明白。我必须把你在纸和笔上说的话形象化:) 必须对接线表是什么做一些额外的研究
  • @HappyCamper:VendorTagID 没有链接到任何东西。这是一个方便、简短、唯一的主键。除了将表作为外键链接之外,所有 ID 字段都没有任何语义含义。这就是为什么它们被称为盲键。任何用户都不应该看到它们。 32 位整数可以达到 20 亿。如果需要更多行,可以使用 64 位整数。
  • @sfxedit:我在 VendorTag 联结表中添加了一个创建的时间戳。通常,联结表具有创建和/或更新时间戳,因此您可以知道何时创建或更新联结。
  • @HappyCamper:如果您只是要显示打开和关闭时间,那么您可以将字符串保存为一列。如果您要对时间进行任何计算,请将它们作为整数“午夜过后的分钟数”保存在数据库中。
【解决方案2】:

创建一个表“vendor_tags”,包含两列,id 和 name。在该表中,您将有类似的行

5,Burgers
8,Desserts
...

“id”列将作为该表的主键。

您的示例中没有“vendor_id”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-30
    • 2016-06-06
    • 2015-02-15
    • 2012-09-01
    • 2015-11-18
    • 2023-03-17
    相关资源
    最近更新 更多