这是一个简单的问题,但我认为我总是使用错误的方式。
我有三个名为 Page 的表 - > 标记 - > 属性。 Tag表接收Page_Id(外键),Attribute表接收Tag_Id(外键)。
属性表也必须收到Page_Id吗?
我从来没有这样做过,但是我看到了一个数据库SQL生成器来执行此操作,因此,我意识到这会使所有工作变得更容易,但这也是正确的方法吗?
使用表格的详细信息进行编辑:Page表格包含HTML页面和一些属性,例如内容,标题,doctype以及html页面的所有其他单个元素。
Tag表包含html页面的HTML标记,其中包含标记(a,p,br,h1,title等)和整个标记等信息。
属性表包含标记的所有属性,就像带有键和值的Map,其中每个条目都是属性和值。
页面包含多个标签(1:N),标签包含多个属性(1:N)。每个表都包含唯一标识。
答案 0 :(得分:2)
这是“依赖”的情况之一 - 你没有,逻辑上需要将值存储在Attribute
中,因为你可以通过加入{来获得这些信息{1}}。
但是,在某些情况下,您可以有用从Tag
“跳转”到Attribute
而无需加入{{1} }。在这种情况下,您可以在Page
中添加Tag
,但是您应该添加其他约束以确保它与Page_Id
中存储的值不一致。
您可以通过在Attribute
中声明两个键来强制执行此一致性 - 您定义的常用键(例如Tag
),以及Tag
和Tag_Id
上的超级键。然后,您将在Tag_Id
中声明包含两个列的外键约束,并引用此超级键。无论你是仅仅Page_Id
,还是仅仅Attribute
的外键约束而,也可以是偏好/风格问题。
如果Tag_Id
s可能会更改Tag
s,那么通常会将超级密钥的外键声明为Page
发生的外键 - 这样,如果UPDATE CASCADE
表中Page_Id
发生更改,则该更改将自动应用于Tag
表。
答案 1 :(得分:1)
没有必要,如果你严格规范化,那么答案应该是“page_id不应该在表格属性上”。但是通常需要(用于报告或仅加快某些操作)来对表进行反规范化,例如在表上添加一个可以通过简单查询获得的字段(如示例中所示)。
答案 2 :(得分:1)
我还没有看到你的桌子结构,所以我必须继续你的描述。这总是有风险的。
如果您的描述意味着页面和标签之间存在1:M关系,并且标签和属性之间存在1:M关系,那么起始关系的样本数据应如下表所示。 (起始关系始终包含所有表的所有属性。)我认为
标记的属性取决于标记显示的页面。 (因此不是标签和属性之间的多值依赖关系。)
Table_A
page_id page_name tag_id tag_name attr_id
--
1 page1 1 tag1 attr1
1 page1 1 tag1 attr2
1 page1 2 tag2 attr1
1 page1 2 tag2 attr3
2 page2 1 tag1 attr1
2 page2 1 tag1 attr2
2 page2 2 tag2 attr1
2 page2 2 tag2 attr2
我们已经从您的说明中了解到page_id - > page_name和tag_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
Table_A中保留了哪些功能,多值或连接依赖项?没有了。唯一的候选键是{page_id,tag_id,attr_id}。我很确定这三个表中至少有5NF。
因此,如果您规范化起始表,则最终会在“last”表中使用page_id。 (顺便说一句,它不再是属性表,是吗?)