如何确定函数依赖性

15

根据我的项目规范,我需要创建一个基于逻辑的数据模型,并确定功能依赖关系。

User 表示例数据:

user_id username    regDate          type subscription
      1    JohnS 01-01-2012 Administrator         NULL
      2   PeterB 02-01-2012     Moderator       Movies
      3   PeterA 02-01-2012          User       Movies
      4     Gary 03-01-2012          User        Books
      5    Irene 03-01-2012          User       Movies
      6     Stan 03-01-2012          User       Movies
      7    Isaac 04-01-2012          User        Books

主键: user_id
唯一键: username
外键: subscription

如何确定函数依赖关系?

我得到了两个函数依赖关系:
user_id -> username, regDate, type, subscription
username -> user_id, regDate, type, subscription

4个回答

7
如果“用户名”既是唯一的,又是必需的(既唯一又非空),那么它就是一个候选键。在关系建模中,一个候选键和另一个候选键之间没有理论上的区别。更具体地说,在关系建模中,没有理论上的理由选择一个候选键并将其标记为“主键”。键就是键。
所以你是对的。这里有两个功能依赖关系。(或者如果把右边分解成单独的列,那就是8个。user_id->usernameuser_id->regDate等)。

但是将其分解成8列不是设计高效数据库的好实践。 - Sahil Babbar
4
将复合的函数依赖关系分解为单个的函数依赖关系,并不等同于将一个关系分解为单个属性。 - Mike Sherrill 'Cat Recall'
还有许多其他持有的FD,这些FD是由提到的FD所暗示的。同时,预计使用此模式属性的其余FD不会持有。考虑到标题是“如何确定功能依赖关系”,这并没有真正回答问题或揭示误解。 - philipxy

6

从理论角度来说,功能依赖如下定义 (Wikipedia):

给定一个关系R,如果在R中有一组属性X能够确定另一组属性Y(写成X → Y),且每个X值都与唯一一个Y值相关联,则称R满足功能依赖X → Y。

从技术角度来看,您正在尝试查找可以唯一标识其他属性的属性。为了简化起见,确定您的候选键和依赖于它们的属性。您的示例是正确的,因为username、regDate、type 和 subscription都取决于user_id的值。如果username是唯一且非空的,则它是一个候选键,并且也可以标识该属性集。


4
很抱歉给你投了反对票,但是当你搜索关于函数依赖时,仅确定候选键是不够的。如果存在传递性函数依赖,则决定因素列集可能不是超键,因此你的答案是不正确的。 - Lajos Arpad

4

我假设你正在使用MySQL,但如果不是,你可以在任何其他关系型数据库管理系统中实现你的想法。

运行以下命令以获取所有表格:

show tables;

然后迭代所有的表格,并对每个表格运行以下命令:

show columns;

FDs可以描述如下:

Determinant -> Dependent,
Determinant = {A1, ..., Am},
Dependent = {B1, ..., Bn}

其中AiBj是列。您需要为DeterminantDependent生成所有可能的情况。对于每种情况,您需要查看是否存在至少两个不同的记录,其中确定列匹配且至少有一个依赖列不匹配。如果是,则该场景不是FD,否则它是FD。例如:假设m = 3,n = 2:

select count(*)
from mytable t1,
mytable t2
where ((t1.A1 = t2.A1) and 
       (t1.A2 = t2.A2) and 
       (t1.A3 = t2.A3)
      ) and 
      (
       (t1.B1 <> t2.B1) or
       (t1.B2 <> t2.B2)
      )
;

将返回违反FD规则的记录数。如果值为0,则场景是FD。

当然,在您的特定情况下,您可以省略一些步骤,并且您有自己的列而不是AiBj,但您希望理解这个想法。


3
我想补充一下,这对一些人来说可能很明显,但仍值得特别提及。缺乏反驳并不能证明FD的存在,因此如果您没有找到给定FD的反例,仍不能保证该FD是有效的。当然,这仅适用于您在处理将存储在数据库中的元组的子集时,因为新数据可以推翻FD。 - Mitchell Carroll
@MitchellCarroll,如果你观察到一个FD,那么它就是一个FD。仅仅因为你发现了一个FD,并不能确定这个FD只适用于现在还是未来也一定会被满足。在我的一项关于CFD(条件函数依赖)的研究中,CFD是仅在满足条件时才适用的FD,我将依赖关系(D)分为表面依赖(AD)和真实依赖(RD)。 - Lajos Arpad
ADs是依赖项,它们在特定时刻为真,而RDs是依赖项,在任何给定时刻都保证为真。基本上,如果您知道D是RD,则可以防止插入/更新违反这些的情况。我编写了代码,自动查找依赖项,如果这些依赖项被验证为RD,则任何插入/更新将违反这些依赖项将引发异常。这样,系统可以自动找到错误,并在错误日志中精确地确定其位置。 - Lajos Arpad
1
你说得很有道理,但如果你试图仅从数据而没有额外信息中找到FDs,那么RDs不存在。一切都只是可能需要被废弃的AD。 - Mitchell Carroll
1
@LajosArpad 是的,现在更易懂了,感谢! - Ahmed Alhallag
显示剩余4条评论

3
除了其他人说的,如果一个属性(或一组属性)是候选键,则所有属性必须在它上面具有功能依赖。
  • "功能依赖" A→B 简单地意味着没有两个不同的B值与同一个A相关。稍微更正式的定义在维基百科上给出,但本质上就是这样。
  • 由于关键字必须是唯一的,即使两个元组包含某些属性的相同值,关键字值也必须不同。因此,不同的值永远不能与相同的关键字值相关。

由于所有属性都在关键字上具有功能依赖,如果存在任何其他功能依赖,您将自动拥有一个传递依赖和违反3NF的情况。因此,“非键”依赖可以作为发现规范化错误的警示。


您还可以从相反的方向考虑:首先确定哪些功能依赖在您的领域中有意义,然后使用它们来确定哪些属性可以充当键。


有一些有效的情况下,不建议使用第三范式(3NF)。如果您有许多记录,并且一些列可以使用某些功能从其他列派生出来,那么在许多情况下,最好计算它们一次,仅在以后读取它们,而不是每次使用它们时都要重新计算值。 - Lajos Arpad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接