MSSQL documentation has a good sample stored procedure (though far from perfect, as Martin noted in the comments about how it does not use QUOTENAME
, for one) for cleaning a temporal table:
DROP PROCEDURE IF EXISTS sp_CleanupHistoryData;
GO
CREATE PROCEDURE sp_CleanupHistoryData
@temporalTableSchema sysname
, @temporalTableName sysname
, @cleanupOlderThanDate datetime2
AS
DECLARE @disableVersioningScript nvarchar(max) = '';
DECLARE @deleteHistoryDataScript nvarchar(max) = '';
DECLARE @enableVersioningScript nvarchar(max) = '';
DECLARE @historyTableName sysname
DECLARE @historyTableSchema sysname
DECLARE @periodColumnName sysname
/*Generate script to discover history table name and end of period column for given temporal table name*/
EXECUTE sp_executesql
N'SELECT @hst_tbl_nm = t2.name, @hst_sch_nm = s.name, @period_col_nm = c.name
FROM sys.tables t1
JOIN sys.tables t2 on t1.history_table_id = t2.object_id
JOIN sys.schemas s on t2.schema_id = s.schema_id
JOIN sys.periods p on p.object_id = t1.object_id
JOIN sys.columns c on p.end_column_id = c.column_id and c.object_id = t1.object_id
WHERE
t1.name = @tblName and s.name = @schName'
, N'@tblName sysname
, @schName sysname
, @hst_tbl_nm sysname OUTPUT
, @hst_sch_nm sysname OUTPUT
, @period_col_nm sysname OUTPUT'
, @tblName = @temporalTableName
, @schName = @temporalTableSchema
, @hst_tbl_nm = @historyTableName OUTPUT
, @hst_sch_nm = @historyTableSchema OUTPUT
, @period_col_nm = @periodColumnName OUTPUT
IF @historyTableName IS NULL OR @historyTableSchema IS NULL OR @periodColumnName IS NULL
THROW 50010, 'History table cannot be found. Either specified table is not system-versioned temporal or you have provided incorrect argument values.', 1
/*Generate 3 statements that will run inside a transaction: SET SYSTEM_VERSIONING = OFF, DELETE FROM history_table, SET SYSTEM_VERSIONING = ON */
SET @disableVersioningScript = @disableVersioningScript + 'ALTER TABLE [' + @temporalTableSchema + '].[' + @temporalTableName + '] SET (SYSTEM_VERSIONING = OFF)'
SET @deleteHistoryDataScript = @deleteHistoryDataScript + ' DELETE FROM [' + @historyTableSchema + '].[' + @historyTableName + ']
WHERE ['+ @periodColumnName + '] < ' + '''' + convert(varchar(128), @cleanupOlderThanDate, 126) + ''''
SET @enableVersioningScript = @enableVersioningScript + ' ALTER TABLE [' + @temporalTableSchema + '].[' + @temporalTableName + ']
SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [' + @historyTableSchema + '].[' + @historyTableName + '], DATA_CONSISTENCY_CHECK = OFF )); '
BEGIN TRAN
EXEC (@disableVersioningScript);
EXEC (@deleteHistoryDataScript);
EXEC (@enableVersioningScript);
COMMIT;
Just add a few extra lines to handle removing data from the parent table and you should be in business.
Bonus: it uses sysname for variables which I am a huge proponent of but is generally an overlooked datatype!