某电商平台设计了如下两个表:
订单表(orders):包含字段为:订单号(order_id)、用户编号(user_id)、商品编号(product_id)、商品名称(product_name)、优惠券编号(coupon_id)、订单时间(order_time)、订单金额(order_amount)、订单状态(order_status)
用户表(users):包含字段为:用户编号(user_id)、用户名(user_name)、累计金额(total_amount)、用户VIP级别(user_vip_level)
现要求对数据库进行范式优化,并设计一个触发器用于在订单插入后自动更新用户的VIP等级。
对订单表进行分解,使其满足 BCNF 范式
订单主表:订单号, 用户编号, 商品编号, 优惠券编号, 订单时间, 订单金额, 订单状态
商品表:商品编号, 商品名称
原始 orders 中除主码 order_id 外还存放 product_name,存在如下函数依赖:order_id → user_id, product_id, product_name, coupon_id, order_time, order_amount, order_status 与 product_id → product_name。由于 product_id 不是候选码 却能决定 product_name,违反 BCNF(Boyce-Codd 正规形)“每个决定因素都必须是候选码”的要求。
为消除该 非键决定因素 带来的冗余与更新异常(如修改商品名需批量更新订单、删除最后一笔订单导致商品名丢失等),采用模式分解:将与商品维度相关的依赖剥离到独立的 products 表(主码 product_id),订单事实留在 orders_core(主码 order_id)。分解后,orders_core 内仅存在由候选码 order_id 决定的依赖,products 内由候选码 product_id 决定 product_name,两表各自 满足 BCNF,同时降低存储冗余并消除插入/删除/更新异常。