-- ====================================================== -- DYNAMIC COLUMN DATA TYPE UPDATE SCRIPT (v3) -- ====================================================== SET XACT_ABORT ON; SET NOCOUNT ON; SET LOCK_TIMEOUT 5000; -- avoid hanging forever on busy objects ------------------------------------------------------------ -- CONFIGURATION ------------------------------------------------------------ DECLARE @NewDataType NVARCHAR(100) = 'Varchar(9)'; -- <-- Target datatype DECLARE @ColumnPattern NVARCHAR(100) = '%DUN%'; -- <-- Column/Parameter pattern DECLARE @DryRun BIT = 0 --1 is for print, 0 is for execute ------------------------------------------------------------ ------------------------------------------------------------ -- END STEP 6 FIX ------------------------------------------------------------ -- =============================== -- STEP 4: ALTER TABLE COLUMNS -- =============================== DECLARE @Schema SYSNAME; DECLARE @Table SYSNAME; DECLARE @Column SYSNAME; DECLARE @OldDataType NVARCHAR(128); DECLARE @AlterSQL NVARCHAR(MAX); DECLARE @IsNullable BIT; -- track nullability DECLARE colCur CURSOR LOCAL FAST_FORWARD FOR SELECT DISTINCT PARSENAME(ObjectName, 2) AS SchemaName, PARSENAME(ObjectName, 1) AS TableName, ColumnName, ColumnDataType FROM DBO.TEMP2 WHERE ObjectType = 'TABLE'; OPEN colCur; FETCH NEXT FROM colCur INTO @Schema, @Table, @Column, @OldDataType; WHILE @@FETCH_STATUS = 0 BEGIN BEGIN TRY -- ==================================================== -- ? Check if column is currently NOT NULL -- so we can preserve it after datatype change -- If original was NOT NULL ? keep NOT NULL -- If original was NULL ? keep NULL -- Without this PK columns become nullable -- and PK recreation fails -- ==================================================== SELECT @IsNullable = c.is_nullable FROM sys.columns c JOIN sys.tables t ON t.object_id = c.object_id JOIN sys.schemas s ON s.schema_id = t.schema_id WHERE s.name = @Schema AND t.name = @Table AND c.name = @Column; -- ? Build ALTER COLUMN with correct nullability SET @AlterSQL = 'ALTER TABLE ' + QUOTENAME(@Schema) + '.' + QUOTENAME(@Table) + ' ALTER COLUMN ' + QUOTENAME(@Column) + ' ' + @NewDataType + -- ? Preserve NOT NULL if column was NOT NULL CASE WHEN @IsNullable = 0 THEN ' NOT NULL' ELSE ' NULL' END; IF @DryRun = 1 INSERT INTO MyprintLog (LogMessage, LogDate) VALUES (@AlterSQL, SYSDATETIME()); ELSE BEGIN PRINT 'Attempting ALTER TABLE: ' + @AlterSQL; EXEC sys.sp_executesql @AlterSQL; insert into dbo.result(objecttype, objectname,ColumnName,ColumnDataType) VALUES('Table',@Table,@Column,@NewDataType) INSERT INTO MyprintLog (LogMessage, LogDate) VALUES (@AlterSQL, SYSDATETIME()); END END TRY BEGIN CATCH DECLARE @CatchMsg5 NVARCHAR(MAX) = ERROR_MESSAGE(); DECLARE @CatchXact5 SMALLINT = XACT_STATE(); DECLARE @CatchObjName5 NVARCHAR(512) = @Schema + '.' + @Table; PRINT '=== ERROR [ALTER_COLUMN] === MSG: ' + @CatchMsg5; IF @CatchXact5 = -1 ROLLBACK TRANSACTION; EXEC dbo.usp_LogError @Step = 'ALTER_COLUMN', @ObjectType = 'TABLE', @ObjectName = @CatchObjName5, @ColumnName = @Column, @ColumnDataType = @OldDataType, @ErrorMessage = @CatchMsg5, @SqlStatement = @AlterSQL, @XactState = @CatchXact5; --THROW; END CATCH FETCH NEXT FROM colCur INTO @Schema, @Table, @Column, @OldDataType; END CLOSE colCur; DEALLOCATE colCur; PRINT '--- RECREATING SCHEMA-BOUND VIEWS ---'; -- =============================== -- Recreating schema bound views -- =============================== DECLARE @CreateSQL2 NVARCHAR(MAX); DECLARE @OBJNAME NVARCHAR(MAX) DECLARE curCreate1 CURSOR FAST_FORWARD FOR SELECT createscript, ViewFullName FROM SchemaBoundViews ; OPEN curCreate1; FETCH NEXT FROM curCreate1 INTO @CreateSQL2,@OBJNAME; PRINT '--- RECREATING SCHEMA-BOUND VIEWS ---'; WHILE @@FETCH_STATUS = 0 BEGIN begin try PRINT 'Creating view:'; SET @CreateSQL2 = SUBSTRING( @CreateSQL2, CHARINDEX('CREATE VIEW', UPPER(@CreateSQL2)), LEN(@CreateSQL2) ); -- ? Convert to CREATE OR ALTER so it works whether view exists or not SET @CreateSQL2 = REPLACE(@CreateSQL2, 'CREATE VIEW', 'CREATE OR ALTER VIEW'); PRINT '--- RECREATING SCHEMA-BOUND VIEWS ---'; IF @DryRun = 1 INSERT INTO MyprintLog (LogMessage, LogDate) VALUES (CONCAT('-- DRYRUN ALTERING ', @OBJNAME, ' ', @CreateSQL2), SYSDATETIME()); ELSE PRINT '== [RECREATE_SCHEMABOUNDVIEWS] === MSG: '+@OBJNAME EXEC sys.sp_executesql @CreateSQL2; INSERT INTO MyprintLog (LogMessage, LogDate) VALUES ('== [RECREATE_SCHEMABOUNDVIEWS] === MSG: '+@OBJNAME, SYSDATETIME()); END TRY BEGIN CATCH DECLARE @CatchMsg10 NVARCHAR(MAX) = ERROR_MESSAGE(); DECLARE @CatchXact10 SMALLINT = XACT_STATE(); PRINT '=== ERROR [RECREATE_SCHEMABOUNDVIEWS] === MSG: ' + @CatchMsg10; IF @CatchXact10 <> -1 EXEC dbo.usp_LogError @Step = 'RECREATE_OBJECT', @ObjectType = 'SCHEMABOUNDVIEWS', @ObjectName = @OBJNAME, @ColumnName = NULL, @ColumnDataType = NULL, @ErrorMessage = @CatchMsg10, @SqlStatement = @CreateSQL2, @XactState = @CatchXact10; --THROW; END CATCH; FETCH NEXT FROM curCreate1 INTO @CreateSQL2,@OBJNAME; END CLOSE curCreate1; DEALLOCATE curCreate1;