Я не уверен, есть ли у нас такая же проблема, но мне потребовалось большое количество «предложенных» изменений в текущем наборе данных (с цепочками предложений, т. Е. С предложением о предложении).
Подумайте о ветвлении в управлении исходным кодом, но для таблиц базы данных.
Мы также хотели получить исторический журнал, но это был наименее важный фактор - основной проблемой было управление предложениями об изменениях, которые могли зависать в течение 6 месяцев или дольше, поскольку бизнес размышлял над утверждением изменений и готовился к фактическому внедрению изменений. .
Идея состоит в том, что пользователи могут загрузить Изменение и начать создавать, редактировать, удалять текущее состояние данных без фактического применения этих изменений. Отмените любые изменения, которые они могли внести, или отмените все изменение.
Единственный способ добиться этого - это иметь набор общих полей в моих версионных таблицах:
Root ID : Обязательно - задайте один раз первичный ключ при создании первой версии записи. Это представляет первичный ключ за все время и копируется в каждую версию записи. Вы должны учитывать Root ID при именовании столбцов отношения (например, PARENT_ROOT_ID вместо PARENT_ID). Поскольку Root ID также является первичным ключом начальной версии, внешние ключи могут быть созданы для фактического первичного ключа - фактическая желаемая строка будет определяться фильтрами версий, определенными ниже.
Изменение ID : Обязательно - каждая запись создается, обновляется, удаляется с помощью изменения
Скопировано с идентификатора : Nullable - null указывает на вновь созданную запись, not-null указывает, с какого идентификатора записи эта строка была клонирована при обновлении
Действует с даты / времени : Nullable - ноль указывает на предложенную запись, not-null указывает, когда запись стала текущей. К сожалению, уникальный индекс не может быть помещен в Root ID / Effective From, поскольку для любого Root ID может быть несколько нулевых значений. (Если вы не хотите ограничивать себя одним предложенным изменением для каждой записи)
Действует до даты / времени : Nullable - null указывает текущий / предложенный, not-null указывает, когда он стал историческим. Технически не требуется, но помогает ускорить запросы для поиска текущих данных. Это поле может быть повреждено вручную, но в этом случае его можно восстановить из даты и времени вступления в силу.
Удалить флаг : Boolean - установите в значение true, когда предлагается удалить запись после ее появления. Когда удаления фиксируются, для их параметра «Дата вступления в силу / время» устанавливается то же значение, что и для параметра «Дата и время вступления в силу», что позволяет отфильтровать их по текущему набору данных.
Запрос на получение текущего состояния данных в соответствии с изменением будет:
SELECT * FROM table WHERE (CHANGE_ID IN :ChangeId OR (EFFECTIVE_FROM <= :Now AND (EFFECTIVE_TO IS NULL OR EFFECTIVE_TO > :Now) AND ROOT_ID NOT IN (SELECT ROOT_ID FROM table WHERE CHANGE_ID IN :ChangeId)))
(Фильтрация кратных изменений при изменении производится вне этого запроса).
Запрос на получение текущего состояния данных в определенный момент времени будет:
SELECT * FROM table WHERE EFFECTIVE_FROM <= :Now AND (EFFECTIVE_TO IS NULL OR EFFECTIVE_TO > :Now)
Общие индексы, созданные для (ROOT_ID, EFFECTIVE_FROM), (EFFECTIVE_FROM, EFFECTIVE_TO) и (CHANGE_ID).
Если кто-нибудь знает лучшее решение, я хотел бы услышать об этом.