Script to update the dates on AdventureWorks database

In case you ever needed this:

IF OBJECT_ID('tempdb..#GeneratedScripts') IS NOT NULL DROP TABLE #GeneratedScripts;
CREATE TABLE #GeneratedScripts (Id INT IDENTITY(1,1), SqlScript NVARCHAR(MAX));
-- 1. Setup global ceiling
INSERT INTO #GeneratedScripts (SqlScript) VALUES ('DECLARE @TargetCeiling DATETIME = GETDATE();');
DECLARE @SchemaName NVARCHAR(256), @TableName NVARCHAR(256), @AnchorColumn NVARCHAR(256);
DECLARE @Sql NVARCHAR(MAX), @ColumnUpdates NVARCHAR(MAX);
DECLARE tbl_cursor CURSOR FOR
SELECT DISTINCT SCHEMA_NAME(t.schema_id), t.name
FROM sys.tables t
JOIN sys.columns c ON t.object_id = c.object_id
JOIN sys.types y ON c.user_type_id = y.user_type_id
WHERE y.name IN ('datetime', 'datetime2')
AND t.is_ms_shipped = 0
AND t.temporal_type <> 1;
OPEN tbl_cursor;
FETCH NEXT FROM tbl_cursor INTO @SchemaName, @TableName;
WHILE @@FETCH_STATUS = 0
BEGIN
-- Pick Anchor Column
SET @AnchorColumn = NULL;
SELECT TOP 1 @AnchorColumn = c.name FROM sys.columns c JOIN sys.types y ON c.user_type_id = y.user_type_id
WHERE c.object_id = OBJECT_ID('[' + @SchemaName + '].[' + @TableName + ']') AND y.name IN ('datetime', 'datetime2')
ORDER BY CASE WHEN c.name = 'ModifiedDate' THEN 0 ELSE 1 END;
SET @ColumnUpdates = '';
SELECT @ColumnUpdates = @ColumnUpdates + '[' + c.name + '] = DATEADD(DAY, src.DayDiff, [' + c.name + ']), '
FROM sys.columns c JOIN sys.types y ON c.user_type_id = y.user_type_id
WHERE c.object_id = OBJECT_ID('[' + @SchemaName + '].[' + @TableName + ']')
AND y.name IN ('datetime', 'datetime2') AND c.is_computed = 0 AND c.generated_always_type = 0;
IF LEN(@ColumnUpdates) > 0
BEGIN
SET @ColumnUpdates = LEFT(@ColumnUpdates, LEN(@ColumnUpdates) - 1);
-- Logic: Disable triggers for this table, update, then re-enable triggers.
-- This fixes Msg 4083 / Trigger conflict issues.
SET @Sql = '
ALTER TABLE [' + @SchemaName + '].[' + @TableName + '] DISABLE TRIGGER ALL;
UPDATE t SET ' + @ColumnUpdates + '
FROM [' + @SchemaName + '].[' + @TableName + '] AS t
CROSS JOIN (SELECT DATEDIFF(DAY, MAX([' + @AnchorColumn + ']), @TargetCeiling) AS DayDiff FROM [' + @SchemaName + '].[' + @TableName + ']) AS src
WHERE src.DayDiff > 0;
ALTER TABLE [' + @SchemaName + '].[' + @TableName + '] ENABLE TRIGGER ALL;' ;
INSERT INTO #GeneratedScripts (SqlScript) VALUES (@Sql);
END
FETCH NEXT FROM tbl_cursor INTO @SchemaName, @TableName;
END
CLOSE tbl_cursor; DEALLOCATE tbl_cursor;
-- Output the results
SELECT SqlScript FROM #GeneratedScripts ORDER BY Id;

What it does, in short: sets a ceiling (of today, including hour, minutes, seconds, milliseconds). It searches for all the user tables (well, it excludes historical and replicated ones) that have a column of DATETIME/DATETIME2() data types (except for the columns used for historical tables, computed columns) and brings them to as close to today as possible).
Of course it can be improved, well aware of that.
Can be used on other databases, so give it a try.
That’s it.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.