Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database 表必须接收外键吗?_Database_Normalization_Rdbms - Fatal编程技术网

Database 表必须接收外键吗?

Database 表必须接收外键吗?,database,normalization,rdbms,Database,Normalization,Rdbms,这是一个简单的问题,但我想我总是用错了方法 我有三个名为Page->Tag->Attribute的表。标记表接收页面Id(外键),属性表接收标记Id(外键) 属性表也必须接收页面Id? 我从来没有这样做过,但我看到一个数据库SQL生成器可以这样做,所以,我意识到这使所有的工作变得更容易,但这也是正确的方法吗 编辑表的详细信息:页面表包含HTML页面和一些属性,如内容、标题、doctype和HTML页面的所有其他单个元素 标签表包含HTML页面的HTML标签,其中包含标签(a、p、br、h1、标

这是一个简单的问题,但我想我总是用错了方法

我有三个名为Page->Tag->Attribute的表。标记表接收页面Id(外键),属性表接收标记Id(外键)

属性表也必须接收页面Id?

我从来没有这样做过,但我看到一个数据库SQL生成器可以这样做,所以,我意识到这使所有的工作变得更容易,但这也是正确的方法吗


编辑表的详细信息:页面表包含HTML页面和一些属性,如内容、标题、doctype和HTML页面的所有其他单个元素

标签表包含HTML页面的HTML标签,其中包含标签(a、p、br、h1、标题等)和整个标签等信息

属性表包含标记的所有属性,就像一个带有键和值的映射,其中每个条目都是一个属性和一个值

页面包含多个标记(1:N),标记包含多个属性(1:N)。每个表都包含一个唯一的标识。

这是一种“视情况而定”的情况-从逻辑上讲,您不需要将值存储在
属性中,因为您可以通过加入
标记来派生此信息

但是,在某些情况下,您可以从
属性
跳到
页面
,而不必加入
标记
,这可能会很有用。在这种情况下,您可以在
属性
中包含
页面Id
,但您应该添加额外的约束,以确保它与
标记
中存储的值不一致


您可以通过在
Tag
中声明两个键来实现此一致性-您定义的常用键(例如
Tag\u Id
),以及
Tag\u Id
Page\u Id
上的超级键。然后在
属性
中声明一个包含两列的外键约束,并引用此超键。您是否这样做,而不是仅对标记Id执行外键约束,或者除此之外,还可以执行外键约束,这也可能取决于您的偏好/风格


如果
标记
s很可能会更改
页面
s,那么您通常会将超级键的外键声明为发生
更新级联
的外键-这样,如果
标记
表中的
页面Id
发生更改,该更改将自动应用于
属性表中。

这是一种“视情况而定”的情况-从逻辑上讲,您不需要将值存储在
属性中,因为您可以通过加入
标记来获取此信息

但是,在某些情况下,您可以从
属性
跳到
页面
,而不必加入
标记
,这可能会很有用。在这种情况下,您可以在
属性
中包含
页面Id
,但您应该添加额外的约束,以确保它与
标记
中存储的值不一致


您可以通过在
Tag
中声明两个键来实现此一致性-您定义的常用键(例如
Tag\u Id
),以及
Tag\u Id
Page\u Id
上的超级键。然后在
属性
中声明一个包含两列的外键约束,并引用此超键。您是否这样做,而不是仅对标记Id执行外键约束,或者除此之外,还可以执行外键约束,这也可能取决于您的偏好/风格



如果
标记
s很可能会更改
页面
s,那么您通常会将超级键的外键声明为发生
更新级联
的外键-这样,如果
标记
表中的
页面Id
发生更改,该更改将自动应用于
属性表中。

这是不必要的,如果您正在严格规范化,则答案应该是“页面id不应位于表属性上”。但是通常需要(用于报告或加速某些操作)对表进行反规范化,例如,在表上添加一个字段,您可以通过简单的查询(如您的示例中)获得该字段。

这是不必要的,如果您严格规范化,那么答案应该是“页面id不应位于表属性上”。但是通常需要(用于报告或加速某些操作)对表进行反规范化,例如在表上添加一个字段,您可以通过简单的查询(如您的示例)获得该字段。

我没有看到您的表结构,因此我必须继续您的描述。那总是有风险的

如果您的描述意味着页面和标记之间存在1:M关系,标记和属性之间存在1:M关系,那么起始关系的示例数据应该与下表类似。(起始关系总是包含所有表的所有属性。)

  • page_id应该标识一个页面
  • tag_id用于识别标签,以及
  • 标记的属性取决于该标记显示的页面。(因此标记和属性之间没有多值依赖关系。)

根据您的描述,我们已经知道页面id->页面名称和标签id->标签名称。(除非你想伤害自己,否则也可以使用page_name->page_id和tag_name->tag_id。)因此,让我们根据这些知识投影新表

Table_C
tag_id  tag_name
--
1       tag1
2       tag2

Table_B
page_id  page_name
--
1        page1
2        page2

Table_A
page_id  tag_id  attr_id
--
1        1       attr1
1        1       attr2
1        2       attr1
1        2       attr3
2        1       attr1
2        1       attr2
2        2       attr1
2        2       attr2
表A中还保留哪些函数依赖项、多值依赖项或联接依赖项?没有。唯一的候选键是{page\u id,tag\u id,attr\u id}。我很确定这三张桌子都至少有5NF

因此,如果对起始表进行规范化,则最终会在“last”表中显示页面id。(顺便说一句,它不再是一个真正的属性表了,是吗?

我还没有看到y
Table_C
tag_id  tag_name
--
1       tag1
2       tag2

Table_B
page_id  page_name
--
1        page1
2        page2

Table_A
page_id  tag_id  attr_id
--
1        1       attr1
1        1       attr2
1        2       attr1
1        2       attr3
2        1       attr1
2        1       attr2
2        2       attr1
2        2       attr2