is it possible to capture the SysEndTime temporal timestamp with an OUTPUT keyword?
For example:
DECLARE @MyTableVar TABLE (sysendtime datetime2);
DELETE
FROM dbo.someTable
OUTPUT DELETED.sysendtime INTO @MyTableVar
WHERE
colA = 'something';
SELECT sysendtime FROM @MyTableVar;
The last SELECT is returning 9999-12-31 23:59:59.000 which is the value before the DELETE exec'd.
I read that SysEndTime is set at the end of the transaction so it wouldn't be visible until all the calls in that blocked completed but that'd mean I'd have to do a secondary query on the someTable table using the "for system_time all" syntax and retrieving the max(SysEndTime) column to capture the most recent change and with that I wouldn't be guaranteed that it's the delete that as an UPDATE would set SysEndTime too.
No this is not possible through the OUTPUT
clause because the value does not exist in a column in the system versioned table.
SQL Server uses the transaction start time - not end time so logically it shouldn't be inherently impossible. The execution plan calls systrandatetime()
in the compute scalar to get the value to use when inserting to the history table.
This is an internal function though and not exposed to us. The following query run in the same transaction should likely return something close but this is datetime
datatype so will get the legacy rounding behaviour to 1/300
of a seconds. I doubt that you will find any guarantees that this even uses the exact same underlying data source either.
SELECT transaction_begin_time
FROM sys.dm_tran_active_transactions
WHERE transaction_id = (SELECT transaction_id
FROM sys.dm_tran_current_transaction);
I would not suggest using the transaction DMVs directly. However as the row already exists in the history table when the DELETE
statement finishes you can (inside the same transaction) just query the history table to get the highest sysendtime
for the primary key of one of the deleted rows (the PK can be captured with OUTPUT
if needed).
e.g. Setup
CREATE TABLE dbo.someTable
(
PK INT PRIMARY KEY,
ColA VARCHAR(15),
[ValidFrom] datetime2 (2) GENERATED ALWAYS AS ROW START ,
[ValidTo] datetime2 (2) GENERATED ALWAYS AS ROW END ,
PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.someTableHistory))
INSERT INTO dbo.someTable
(PK,
ColA)
VALUES (1,'something'),
(2,'something');
Then you could achieve this as below
DECLARE @DeletedPks TABLE
(
PK INT
)
BEGIN TRAN
DELETE FROM dbo.someTable
OUTPUT DELETED.PK
INTO @DeletedPks
WHERE colA = 'something';
SELECT MAX(ValidTo)
FROM dbo.someTableHistory
WHERE PK = (SELECT TOP 1 PK /*Doesn't matter which PK we choose*/
FROM @DeletedPks)
COMMIT