我们正在为客户编写MIS代码。特定产品的价格经常变化,客户需要维持价格有效的价格和日期。有一个名为PRODUCT_PRICE
的表来维护其DDL简单显示如下的价格。
CREATE TABLE `PRODUCT_PRICE` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`product_id` bigint(20) NOT NULL DEFAULT 0 COMMENT 'product id',
`price` bigint(20) NOT NULL DEFAULT 0 COMMENT 'price value in cent',
`start_date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'when this price takes effect',
`del_flag` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT 'mark if logically deleted',
`status` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '0 new, 1 wait for audit, 2 accepted, 3 rejected',
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='product price table'
请注意,DDL中没有end_date
,因为它恰好是下一条记录start_date
的前一天,如果没有下一条记录,则为无限。
在系统中,每当有人在系统中创建或编辑某些产品的价格时,信息将被发送给管理员进行审核和审核。除非管理员接受,否则更改不会生效。可以再次编辑通过审核和审核的PRODUCT_PRICE
。
问题在于,在我们的旧设计中,PRODUCT_PRICE
的特定记录将立即更改,status
字段翻转为0以等待审核和审核。 但这不是客户想要的。
新要求是,除非管理员接受新的price
或start_date
,否则人们仍可以在有人编辑后查看通过审核的价格记录。
我们应该如何重构旧表设计以实现新的要求,即除非管理员接受更改,否则某个记录的更改不会立即生效。
经过讨论,我们找到了2个解决方案。
每当有人更改系统中的PRODUCT_PRICE
记录时,将创建包含新信息的行,并将其发送以进行审核。接受后,旧的将被删除。因此,应在表格中添加新列reference_id
以标记某个旧记录以进行更改。
创建新表PRODUCT_PRICE_TEMP
以存储等待审核的所有新价格记录。接受后,更新PRODUCT_PRICE
中的某个旧记录。此解决方案还需要列reference_id
来引用PRODUCT_PRICE
中的某一行,但我们无需删除PRODUCT_PRICE
中的记录以更改值(仅更新)。
我们的新要求是否有更好的设计?
答案 0 :(得分:0)
你的第一个解决方案就是它。
尝试从鸟类视图中查看问题,从数据库模型中抽象出来。每次价格变动系统都会创建产品价格项的新实例。 从用户的角度来看,这是一个变化,对于系统来说,它是一个新的实体。好像你已经想出来了。
更重要的是 - 让我警告你这样做:"旧的将被删除"。我认为背后的假设是产品价格开始日期可能是过去的。这是非常危险的,以后会引起可怕的并发症。 过去的价格变动必须是罕见的例外情况,而非正常情况。
当然还是会发生因为人们会犯错误。对于这种关键(并且罕见!)情况,您需要给予一个或两个高级人员(或管理员/支持人员)在未经任何批准的情况下更改过去的价格的能力。可能直接在DB中。没有时间,公司每秒都在亏钱。通常,同一个人以后会处理错误定价对客户和账单的所有后果。即使在这种情况下,您也不应该编辑product_price中的行,将旧的行标记为无效并从过去开始创建新行。