воскресенье, 15 января 2023 г.

Кейс: изменение значения бизнес-ключа

Возьмем некоторую сущность модели данных, экземпляры которой идентифицируются бизнес-ключом. Бизнес-ключ - это код или номер, который известен конечным пользоватлям системы (представлен в пользовательском интерфейсе) и используется в коммуникациях. Например, артикул товара, код подразделения компании, табельный номер сотрудника. Когда один сотрудник передает другому список товаров, он передает список артикулов. Когда подразделение компании заводит заявку на обслуживание, оно указывает код подразделения; этот же код подразделения фигурирует в копроративных отчетах.

Бизнес-ключ, как правило, имеется у справочников (страны, типы заказа, ...), ресурсных сущностей (товар, поставщик, ...) и операционных сущностей (заказ, промо-акция, ...). Другие сущности (конфигурации, бизнес-транзакции) используют внешние бизнес-ключи как часть собственного уникального ключа.

Бывает, что бизнес-ключ изменяется пользователем.

Изменение бизнес-ключа оправдано, если была сделана ошибка при его первоначальном вводе. Мог быть нарушен формат кода или введено неправильное значение. Само собой, что ручной ввод бизнес-ключей разрешается только привилегированным пользователям, которые осознают ответственность, связанную с вводом бизнес-ключа, и потому семь раз отмерят, прежде чем резать. Но и на старуху бывает проруха. Не ошибается тот, кто не пьет шампанского.

Но если ошибка замечена и исправлена быстро, какая в том беда? А вот какая.

Бизнес-ключ в корпоративной модели данных является уникальным идентификатором экземпляра бизнес-сущности, и в силу этого используется не в одной только системе, куда его вводит пользователь, но в разных системах компании. Системы интегрированы при помощи сообщений об изменениях, отправляемых системой-источником, и получаемых и обрабатываемых системами-приемниками.

Предположим, есть бизнес-сущность Товар с бизнес-ключом Артикул и описательным атрибутом Название. Необходимо ввести в систему данные о товаре с артикулом "ABC" и названием "Шар голубой".

При вводе данных пользователь допустил ошибку и ввел товар с неправильным артикулом "ABB" и правильным названием "Шар голубой". Система отправляет подписчикам сообщение об изменении товара {"операция": "создание", "артикул": "ABB", "название": "Шар голубой"}. Другая система получает это сообщение и создает в своей таблице запись о товаре с артикулом "ABB".

Между тем пользователь исправляет ошибку и меняет артикул уже введенного товара с "ABB" на "ABC". Теперь и артикул и название товара в первичной системе правильные, и система отправляет сообщение об изменении {"операция": "изменение", "артикул": "ABC", "название": "Шар голубой"}. Другая система, получив это сообщение, пытается обновить в своей таблице товар с артикулом "ABC" - и терпит неудачу, потому что строки с таким значением артикула в ее таблице нет.

Как справиться с такой ситуацией, не нагружая модель данных (и сообщения в шине данных) дополнительным идентификационным кодом, который бы не изменялся при изменении бизнес-ключа? Таким кодом мог бы быть первичный ключ таблицы с товарами из системы-источника, который по определению неизменен в течение всего жизненного цикла строки. Однако, он ничего не говорит пользователям, решая чисто техническую задачу в БД, и, таким образом, не дает оснований для распространения его в другие системы.

Решить проблему можно, приняв, что поле с бизнес-ключом в сообщении всегда содержит значение бизнес-ключа до его изменения, а новое значение ключа передается в необязательном поле "новый_артикул". Это поле будет добавляться в сообщение системой-источником только в случае изменения артикула товара.

Тогда первое сообщение после ошибочного ввода данных пользоватлем будет таким же, как и раньше, {"операция": "создание", "артикул": "ABB", "название": "Шар голубой"}, и система-получатель создаст в своей таблице товар с артикулом "ABB". А второе сообщение, после исправления пользователем артикула, будет таким: {"операция": "изменение", "артикул": "ABB", "название": "Шар голубой", "новый_артикул": "ABC"}. Система-получаталь обнаружит в сообщении "новый_артикул" со значением "ABC" и обновит в строке таблицы с артикулом "ABB" не только название товара, но и сам артикул - на новое значение "ABC".

Может ли потенциально изменяемый бизнес-ключ в системе-источнике или системе-приемнике быть первичным ключом таблицы?

По-хорошему, не должен.

Но и из хороших правил встречаются исключения. Например, если мы говорим о справочнике, то код статьи справочника удобно иметь в качестве первичного ключа и, следовательно, в качестве внешних ключей в дочерних таблицах, - это позволяет избежать соединений с родительской таблицей при запросах дочерних таблиц по ключу справочника. И чем сложнее запрос, тем целесообразней избегать лишних соединений.

Об изменении значения первичного ключа будет отдельный пост.

Комментариев нет:

Отправить комментарий