#mysql #database #software-design
#mysql #База данных #программное обеспечение-дизайн
Вопрос:
Мы кодируем 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
для изменения значения (просто обновите).
Есть ли лучший дизайн для нашего нового требования?
Ответ №1:
Ваше первое решение почти готово.
Попробуйте взглянуть на проблему с высоты птичьего полета, абстрагируясь от модели db. Каждый раз, когда цена изменяется, система создает новый экземпляр элемента цены продукта. Это изменение с точки зрения пользователя, для системы это новая сущность.Похоже, вы уже поняли это.
Что более важно — позвольте мне предостеречь вас от этого: «старая будет удалена». Я полагаю, что исходное предположение заключается в том, что дата начала цены продукта может быть в прошлом. Это очень опасно, и это может вызвать ужасные осложнения позже. Изменение цены в прошлом должно быть редким исключением, а не нормальной ситуацией.
Конечно, это все еще происходит, потому что люди совершают ошибки. В этой критической (и редкой!) ситуации вам нужно предоставить одному или двум руководящим сотрудникам (или администратору / службе поддержки) возможность изменять цену в прошлом без каких-либо согласований. Вероятно, непосредственно в базе данных. На это просто нет времени, компания теряет деньги каждую секунду. Обычно тот же человек позже позаботится обо всех последствиях неправильного ценообразования для клиентов и счетов. Даже в этой ситуации вам не следует редактировать строку в product_price, помечать старую как недопустимую и создавать новую строку, начинающуюся с прошлого.