【发布时间】:2013-04-14 14:53:41
【问题描述】:
我正忙于一个项目,遇到的绊脚石之一如下:
我有一个预订表,这可能会或可能不会导致发票被开具(因为一些不相关的事情,例如取消)。我将如何强制执行一(在预订方面)到零或一(在发票方面)的关系?到目前为止,这是我所拥有的:
CREATE TABLE IF NOT EXISTS `booking` (
`booking_id` int(11) NOT NULL AUTO_INCREMENT,
`voucher_id` int(11) NOT NULL,
`pickup_date_time` datetime NOT NULL, ...
PRIMARY KEY (`booking_id`,`voucher_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
然后,稍后:
CREATE TABLE IF NOT EXISTS `invoice` (
`booking_id` int(11) NOT NULL,
`voucher_id` int(11) NOT NULL,
`invoice_number` int(11) NOT NULL,
`paid` tinyint(1) NOT NULL,
PRIMARY KEY (`booking_id`,`voucher_id`),
UNIQUE KEY `invoice_number` (`invoice_number`),
KEY `voucher_id` (`voucher_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
voucher_id 只是我在系统中使用的其他东西。 invoice_number也是在PHP中生成的,所以这无关紧要。
任何帮助将不胜感激!
【问题讨论】:
-
我应该补充一点,我讨厌任何可以为空的值。所以任何避免 NULL 的东西都会很棒!
-
我认为您当前的设计没有任何问题。
-
此外,预订中的复合键 - 这意味着我可以拥有 same
booking_id两次,只要我输入不同的 voucher_id?您应该将booking_id设置为 PK 并在voucher_id上添加一个 UNIQUE 约束,以强制凭证只能使用一次。或将“booking_id”带到凭证表(是的,这将是可以为空的)即尚未使用的代金券将具有null作为 booking_id 并在使用后具有现有的 booking_id。 -
不,它没有;首先,自动编号只是协助创建一个新号码,它不会阻止您手动插入带有 booking_id 的记录,这将允许重复的 booking_ids。此外;是否需要需要代金券才能进行预订?最后,如果您想要“无缝”预订 ID(即 不 想要 0001、0005、0006),也不要依赖自动编号,因为插入失败也可能会增加计数器。 IMO,
booking_id是 PK,voucher_id是“优惠券”的外键(如果预订不需要优惠券,则应该可以为空) -
也标记我的第一条评论;这同样适用于发票; PK 应该是
invoice_id,现在预订的 PK 是booking_id,您可以删除voucher_id列。最后要考虑的一件事;如果预订可以应用多个优惠券(例如,如果使用优惠券来获得折扣,并且允许组合它们),则将它们作为 n:m 关系 (HasAndBelongsToMany) 存储在连接表中bookings_vouchers
标签: mysql sql database-design foreign-keys relational-database