Sample Header Ad - 728x90

If a trigger runs an update will it ALWAYS have the same timestamp for a temporal table?

2 votes
2 answers
318 views
Background - Here is an example near to what I am working with: 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 When I run this, this is the first result: |GroupNumber|StartEffectiveWhen|EndEffectiveWhen|ModifiedWhen|IsReady|RowValidFrom|RowValidTo| |:----|:----|:----|:----|:----|:----|:----| |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|NULL|NULL|1|2024-08-29 23:15:28.5295658|2024-08-29 23:15:28.5764223| |12345|2024-01-01|NULL|NULL|0|2024-08-29 23:15:28.4826980|2024-08-29 23:15:28.5295658| And the second set of output looks like this: |GroupNumber|StartEffectiveWhen|EndEffectiveWhen|ModifiedWhen|IsReady|RowValidFrom|RowValidTo| |:----|:----|:----|:----|:----|:----|:----| |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|NULL|1|2024-08-29 23:15:28.5764223|2024-08-29 23:15:28.5764223| |12345|2024-01-01|NULL|NULL|1|2024-08-29 23:15:28.5295658|2024-08-29 23:15:28.5764223| |12345|2024-01-01|NULL|NULL|0|2024-08-29 23:15:28.4826980|2024-08-29 23:15:28.5295658| This is different because the first query result uses the for SYSTEM_TIME ALL clause, while the second one just queries the raw data. The difference is that, in the first data set, the second and third rows of the second data set have been filtered out. They have been removed because the second and third rows have a start date and end date that are the same. (Basically saying those rows were never really in effect.) Question - What I need to know is, can I depend on this "zero time difference" always being there for data that was updated via an AFTER trigger? (I need to write some queries that will fail if this is not the case.) What I mean by that is this: If my server was being hammered by thousands of queries all doing crazy amounts of IO and calculations, would the RowValidFrom and RowValidTo values for the second and third rows of the second dataset still have a difference of 0? Put another way, are these values the same because of transaction logic? Or are they the same because my server is fast and not really under any pressure right now?
Asked by Vaccano (2550 rep)
Aug 29, 2024, 11:25 PM
Last activity: Aug 30, 2024, 12:26 PM