Fundo
Aqui está um exemplo próximo do que estou trabalhando:
CREATE TABLE sandboxTesting.TemporalTest (
GroupNumber VARCHAR(25) NOT NULL,
StartEffectiveWhen DATE NOT NULL,
EndEffectiveWhen DATE NULL,
ModifiedWhen DATETIME NULL,
IsReady BIT NOT NULL DEFAULT 0,
RowValidFrom DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL,
RowValidTo DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME (RowValidFrom, RowValidTo),
CONSTRAINT PK_TemporalTest PRIMARY KEY CLUSTERED
(
GroupNumber, StartEffectiveWhen
)
) WITH (SYSTEM_VERSIONING=ON (HISTORY_TABLE=sandboxTesting.TemporalTestHistory))
GO
CREATE TRIGGER sandboxTesting.OnModify ON sandboxTesting.TemporalTest AFTER UPDATE AS
BEGIN
UPDATE temporalTst
SET temporalTst.IsReady = 0,
temporalTst.ModifiedWhen = GETDATE()
FROM sandboxTesting.TemporalTest temporalTst
JOIN deleted del
ON del.GroupNumber = temporalTst.GroupNumber
AND del.StartEffectiveWhen = temporalTst.StartEffectiveWhen
WHERE -- All business columns go here with OR statements in between them.
-- The idea is that if anything changes except the IsReady flag, then we
-- set the IsReady back to false. (IsReady has to be set by itself)
del.EndEffectiveWhen <> temporalTst.EndEffectiveWhen
OR (del.EndEffectiveWhen IS NULL AND temporalTst.EndEffectiveWhen IS NOT NULL)
OR (del.EndEffectiveWhen IS NOT NULL AND temporalTst.EndEffectiveWhen IS NULL)
END
GO
-- Insert new test
INSERT INTO [sandboxTesting].[TemporalTest] ([GroupNumber], [StartEffectiveWhen], [EndEffectiveWhen], [ModifiedWhen])
VALUES ('12345', '2024-01-1', NULL, NULL)
GO
-- Set is as ready
UPDATE sandboxTesting.TemporalTest
SET IsReady = 1
WHERE GroupNumber = '12345' AND StartEffectiveWhen = '2024-01-1'
GO
-- Change the End date
UPDATE sandboxTesting.TemporalTest
SET EndEffectiveWhen = '2024-09-02'
WHERE GroupNumber = '12345' AND StartEffectiveWhen = '2024-01-1'
-- Set the new end date as ready for billing.
UPDATE sandboxTesting.TemporalTest
SET IsReady = 1
WHERE GroupNumber = '12345' AND StartEffectiveWhen = '2024-01-1'
GO
-- Select the Data
SELECT * FROM sandboxTesting.TemporalTest for SYSTEM_TIME ALL
ORDER BY GroupNumber, StartEffectiveWhen desc, RowValidFrom DESC, RowValidTo DESC, ModifiedWhen desc
-- Select the Raw Data (for comparison)
SELECT * FROM sandboxTesting.TemporalTest
UNION ALL
SELECT * FROM sandboxTesting.TemporalTestHistory
ORDER BY GroupNumber, StartEffectiveWhen desc, RowValidFrom DESC, RowValidTo DESC, ModifiedWhen desc
Quando executo isso, este é o primeiro resultado:
Número do grupo | InícioEfetivoQuando | FimEfetivoQuando | ModificadoQuando | Está pronto | LinhaVálidaDe | LinhaVálidaPara |
---|---|---|---|---|---|---|
12345 | 2024-01-01 | 2024-09-02 | 2024-08-29 17:15:28.587 | 1 | 2024-08-29 23:15:28.5764223 | 9999-12-31 23:59:59.9999999 |
12345 | 2024-01-01 | NULO | NULO | 1 | 2024-08-29 23:15:28.5295658 | 2024-08-29 23:15:28.5764223 |
12345 | 2024-01-01 | NULO | NULO | 0 | 2024-08-29 23:15:28.4826980 | 2024-08-29 23:15:28.5295658 |
E o segundo conjunto de saída se parece com isto:
Número do grupo | InícioEfetivoQuando | FimEfetivoQuando | ModificadoQuando | Está pronto | LinhaVálidaDe | LinhaVálidaPara |
---|---|---|---|---|---|---|
12345 | 2024-01-01 | 2024-09-02 | 2024-08-29 17:15:28.587 | 1 | 2024-08-29 23:15:28.5764223 | 9999-12-31 23:59:59.9999999 |
12345 | 2024-01-01 | 2024-09-02 | 2024-08-29 17:15:28.587 | 0 | 2024-08-29 23:15:28.5764223 | 2024-08-29 23:15:28.5764223 |
12345 | 2024-01-01 | 2024-09-02 | NULO | 1 | 2024-08-29 23:15:28.5764223 | 2024-08-29 23:15:28.5764223 |
12345 | 2024-01-01 | NULO | NULO | 1 | 2024-08-29 23:15:28.5295658 | 2024-08-29 23:15:28.5764223 |
12345 | 2024-01-01 | NULO | NULO | 0 | 2024-08-29 23:15:28.4826980 | 2024-08-29 23:15:28.5295658 |
Isso é diferente porque o primeiro resultado da consulta usa a for SYSTEM_TIME ALL
cláusula, enquanto o segundo apenas consulta os dados brutos.
A diferença é que, no primeiro conjunto de dados, a segunda e a terceira linhas do segundo conjunto de dados foram filtradas. Elas foram removidas porque a segunda e a terceira linhas têm uma data de início e uma data de término que são as mesmas. (Basicamente dizendo que essas linhas nunca estiveram realmente em vigor.)
Pergunta
O que preciso saber é se posso confiar que essa "diferença de tempo zero" sempre estará presente para dados que foram atualizados por meio de um AFTER
gatilho? (Preciso escrever algumas consultas que falharão se esse não for o caso.)
O que quero dizer com isso é o seguinte: se meu servidor estivesse sendo bombardeado por milhares de consultas, todas realizando quantidades absurdas de E/S e cálculos, os valores RowValidFrom
e RowValidTo
para a segunda e terceira linhas do segundo conjunto de dados ainda teriam uma diferença de 0?
Em outras palavras, esses valores são os mesmos por causa da lógica da transação? Ou são os mesmos porque meu servidor é rápido e não está realmente sob nenhuma pressão agora?