仅给定INVOICE关系无标注无数据时的BCNF转换问题咨询
INVOICE关系BCNF转换的函数依赖推导与实操指导
推导函数依赖的核心判断逻辑
由于没有给定实际业务数据,所有合理的函数依赖都可以锚定常规进销存场景的通用常识,严格满足函数依赖的基本定义:只要决定因素的取值确定,右侧所有属性的取值就唯一无歧义,不存在多值重复的情况,就属于合规的假设,不需要过度纠结“标准答案”,只要在解题开头明确写清楚所有假设即可。
对已推测的函数依赖的合理性校验
你之前写的4条依赖存在部分粒度错位、方向颠倒的问题,逐点拆解:
Number → (CustomerName,CustomerNumber,CustomerAdress):方向和粒度合理。发票号是全局唯一的单据标识,单张发票固定对应一个客户,不存在同票多客户的情况,符合业务逻辑。CustomerNumber → (CustomerName,CustomerAdress):完全合理。客户编号是客户实体的唯一标识,同一客户的姓名、固定地址不会随交易变动,是典型的实体类函数依赖。ItemNumber → (Number,ItemPrice):存在方向性错误。商品编号无法反向决定对应的发票号——同一个商品可以出现在几十张不同的销售发票上,没有唯一性;且商品定价是商品本身的固有属性,和出现在哪张发票无关,这部分正确的逻辑应该修正为ItemNumber → ItemPrice。(Number,ItemNumber) → (ItemQuantity,SalespersonNumber,SalespersonName,Subtotal,Tax,TotalDue):存在粒度混杂问题。销售经办人员、整张发票的税额、应付总额都是整张发票级别的全局属性,不是单条商品行的属性,一张票不会每条商品行换一个销售、算一次不同的税额,不能硬塞到行项粒度的决定因素右侧;同时单条行的小计是行级属性,和全局属性不属于同一粒度。
补全后的完整合理函数依赖列表
按属性所属的业务粒度分类写,避免不同粒度的属性混杂:
- 实体/单据单属性粒度的依赖(决定因素为单字段)
- 发票号粒度:
Number → (CustomerNumber, SalespersonNumber, Tax, TotalDue)。这里不把CustomerName、CustomerAdress、SalespersonName放在右侧,是因为这些属性已经可以通过后续的依赖传递得到,不需要重复声明。 - 客户实体粒度:
CustomerNumber → (CustomerName, CustomerAdress) - 销售员工实体粒度:
SalespersonNumber → SalespersonName。这是之前漏写的依赖,销售编号是员工的唯一标识,对应固定的员工姓名。 - 商品实体粒度:
ItemNumber → ItemPrice
- 发票号粒度:
- 发票行项粒度的依赖(决定因素为复合字段,对应单条商品行的标识)
- 发票号+商品编号的组合是单条发票行的唯一标识:
(Number, ItemNumber) → (ItemQuantity, Subtotal)。其中Subtotal就是当前行的商品行小计,和行级属性匹配。
- 发票号+商品编号的组合是单条发票行的唯一标识:
完整BCNF转换步骤
- 第一步:识别初始INVOICE关系的候选键。通过上面的依赖推导,能覆盖所有属性的最小集合是
(Number, ItemNumber):通过Number可以推出票头属性,通过ItemNumber可以推商品单价,两个字段组合可以推出行级属性,再通过传递依赖推出所有剩余的姓名、地址类属性,因此这是初始关系的唯一候选键。 - 第二步:逐组检查所有函数依赖,只要决定因素不是候选键,就拆分为独立的BCNF关系:
- 第一组非候选键决定的依赖:
CustomerNumber → (CustomerName, CustomerAdress)。拆出独立关系CUSTOMER,主键为CustomerNumber,所有属性都由主键直接决定,满足BCNF要求。 - 第二组非候选键决定的依赖:
SalespersonNumber → SalespersonName。拆出独立关系SALESPERSON,主键为SalespersonNumber,满足BCNF要求。 - 第三组非候选键决定的依赖:
ItemNumber → ItemPrice。拆出独立关系ITEM,主键为ItemNumber,满足BCNF要求。 - 拆分完成后,原INVOICE关系拆为两个剩余的子关系,分别匹配粒度:
- 票头关系:
INVOICE_HEADER (Number, CustomerNumber, SalespersonNumber, Tax, TotalDue),主键为Number,所有属性都由Number直接决定,不存在非主键的决定因素,满足BCNF。 - 行项关系:
INVOICE_LINE (Number, ItemNumber, ItemQuantity, Subtotal),复合主键为(Number, ItemNumber),所有属性都由这个复合主键直接决定,不存在非主键的决定因素,满足BCNF。
- 票头关系:
- 第一组非候选键决定的依赖:
- 最后校验:拆分后的5个关系都满足“所有函数依赖的决定因素都是自身关系的主键”的BCNF要求,没有冗余存储,也没有多值依赖冲突。
内容的提问来源于stack exchange,提问作者Eileen
相关产品推荐
相关产品推荐

