Хорошо, похоже, у меня есть потенциальное решение: временные таблицы
Временные таблицы работают в Azure и записывают новую строку в таблицу истории при каждом изменении: -
CREATE TABLE dbo.LMSTemporalTest
(
[EmployeeID] INT NOT NULL PRIMARY KEY CLUSTERED
, [Name] NVARCHAR(100) NOT NULL
, [Position] NVARCHAR(100) NOT NULL
, [Department] NVARCHAR(100) NOT NULL
, [Address] NVARCHAR(1024) NOT NULL
, [AnnualSalary] DECIMAL (10,2) NOT NULL
, [UpdatedBy] UniqueIdentifier NOT NULL
, [UpdatedDate] DateTime NOT NULL
, [ValidFrom] DateTime2 (2) GENERATED ALWAYS AS ROW START HIDDEN
, [ValidTo] DateTime2 (2) GENERATED ALWAYS AS ROW END HIDDEN
, PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.LMSTemporalTestHistory));
GO
Затем я могу вставить запись в таблицу ...
INSERT INTO LMSTemporalTest(EmployeeID,Name,Position,Department,Address,AnnualSalary, UpdatedBy, UpdatedDate)
VALUES(1, 'Bob', 'Builder', 'Fixers','Oops I forgot', 1, '0D7F5584-C79B-4044-87BD-034A770C4985', GetDate())
GO
Обновить строку ...
UPDATE LMSTemporalTest SET
Address = 'Sunflower Valley, Bobsville',
UpdatedBy = '2C62290B-61A9-4B75-AACF-02B7A5EBFB80',
UpdatedDate = GetDate()
WHERE EmployeeID = 1
GO
Обновить строку еще раз ...
UPDATE LMSTemporalTest SET
AnnualSalary = 420.69,
UpdatedBy = '47F25135-35ED-4855-8050-046CD73E5A7D',
UpdatedDate = GetDate()WHERE EmployeeID = 1
GO
А затем проверьте результаты: -
SELECT * FROM LMSTemporalTest
GO
EmployeeID Name Position Department Address AnnualSalary UpdatedBy UpdatedDate
1 Bob Builder Fixers Sunflower Valley, Bobsville 420.69 47F25135-35ED-4855-8050-046CD73E5A7D 2019-07-01 16:20:00.230
Примечание. Поскольку я установил их как Скрытые, Действительные с и Действительные, чтобы не отображаться
Проверьте изменения на дату/ диапазон времени: -
SELECT * FROM LMSTemporalTest
FOR SYSTEM_TIME BETWEEN '2019-Jul-01 14:00' AND '2019-Jul-01 17:10'
WHERE EmployeeID = 1
ORDER BY ValidFrom;
GO
EmployeeID Name Position Department Address AnnualSalary UpdatedBy UpdatedDate
1 Bob Builder Fixers Oops I forgot 1.00 0D7F5584-C79B-4044-87BD-034A770C4985 2019-07-01 16:20:00.163
1 Bob Builder Fixers Sunflower Valley, Bobsville 1.00 2C62290B-61A9-4B75-AACF-02B7A5EBFB80 2019-07-01 16:20:00.197
1 Bob Builder Fixers Sunflower Valley, Bobsville 420.69 47F25135-35ED-4855-8050-046CD73E5A7D 2019-07-01 16:20:00.230
И я даже могу просмотреть таблицу истории
SELECT * FROM LMSTemporalTestHistory
GO
EmployeeID Name Position Department Address AnnualSalary UpdatedBy UpdatedDate ValidFrom ValidTo
1 Bob Builder Fixers Oops I forgot 1.00 0D7F5584-C79B-4044-87BD-034A770C4985 2019-07-01 16:20:00.163 2019-07-01 16:20:00.16 2019-07-01 16:20:00.19
1 Bob Builder Fixers Sunflower Valley, Bobsville 1.00 2C62290B-61A9-4B75-AACF-02B7A5EBFB80 2019-07-01 16:20:00.197 2019-07-01 16:20:00.19 2019-07-01 16:20:00.22
Примечание: текущая строка не отображается, поскольку она по-прежнему действительна
Все наши важные таблицы уже имеют CreatedBy, CreatedDate, updatedBy и updatedDate, поэтому я могу использовать их для регистрации идентификаторов пользователей.Не существует очевидного способа обработки Программы и Версии как стандартного, но я всегда могу добавить другое скрытое поле и использовать Триггеры, чтобы установить это.
РЕДАКТИРОВАТЬ: Фактически протестировано
Первое препятствие было: можетвы фактически изменяете существующую таблицу во временную таблицу, и ответ был: да!
ALTER TABLE Clients ADD
[ValidFrom] DateTime2 (2) GENERATED ALWAYS AS ROW START HIDDEN NOT NULL DEFAULT '1753-01-01 00:00:00.000',
[ValidTo] DateTime2 (2) GENERATED ALWAYS AS ROW END HIDDEN NOT NULL DEFAULT '9999-12-31 23:59:59.997',
PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
GO
ALTER TABLE Clients SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.ClientsHistory))
GO
Важным битом выше являются значения по умолчанию для полей ValidFrom и ValidTo.Это работает только в том случае, если ValidTo является максимальным значением, которое может иметь DateTime2, следовательно, «9999-12-31 23: 59: 59.997».ValidFrom, кажется, не имеет значения, поэтому я установил его на минимум, чтобы охватить все.
Хорошо, поэтому я преобразовал таблицу, но теперь у нее есть два дополнительных поля, которые не в таблице не Azure.Это теоретически скрыто, но будет ли на них жаловаться наше программное обеспечение?
Кажется, нет.Запустил программное обеспечение, отредактировал запись в таблице «Клиенты» и сохранил ее, и программа вообще не жаловалась.
Проверено таблицы «Клиенты и истории клиентов»: -
SELECT * FROM Clients
FOR SYSTEM_TIME BETWEEN '1753-01-01 00:00:00.000' AND '9999-12-31 23:59:59.997'
WHERE sCAccountNo = '0001064'
ORDER BY ValidFrom
Показываетдве записи, исходная и отредактированная, а также существующие поля updatedUser и updatedDate отображаются правильно, поэтому я знаю, кто и когда внес изменения.
SELECT * FROM ClientsHistory
Показывает исходную запись с ValidTo, установленным на датуизменение,
Все кажется хорошим, теперь мне просто нужно убедиться, что он по-прежнему возвращает только текущую запись в запросах и нашему программному обеспечению: -
SELECT * FROM Clients
WHERE sCAccountNo = '0001064'
Просто вернул одну запись,и не отображает скрытые поля ValidFrom и ValidTo.
Выполнил поиск в нашем программном обеспечении для клиента 0001064, и снова он просто возвратил одну запись и не пожаловался на два дополнительных поля.
Еще нужно настроить несколько триггеров и добавить еще одно поле HIDDEN для записи программы и версии из строки подключения, но это выглядит как TemporalТаблицы дают мне жизнеспособную опцию аудита.
Пока единственным недостатком является то, что он создает целую строку записей для каждого набора изменений, то есть вам нужно сравнить ее с другими записями, чтобы выяснить, что изменилось, но я могунаписать что-нибудь, чтобы упростить это достаточно легко.