-- ====================================================== -- 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(TMP.ObjectName, 2) AS SchemaName, PARSENAME(TMP.ObjectName, 1) AS TableName, TMP.ColumnName, TMP.ColumnDataType, c.is_nullable FROM DBO.TEMP2 TMP INNER JOIN sys.schemas s ON s.name = PARSENAME(TMP.ObjectName, 2) INNER JOIN sys.tables t ON t.schema_id = s.schema_id AND t.name = PARSENAME(TMP.ObjectName, 1) INNER JOIN sys.columns c ON c.object_id = t.object_id AND c.name = TMP.ColumnName WHERE TMP.ObjectType = 'TABLE'; OPEN colCur; FETCH NEXT FROM colCur INTO @Schema, @Table, @Column, @OldDataType, @IsNullable; WHILE @@FETCH_STATUS = 0 BEGIN BEGIN TRY -- Nullability is now pre-fetched directly in the cursor declaration. -- Preserving NOT NULL so PK columns do not become nullable. -- ? 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, @IsNullable; 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 LOCAL FAST_FORWARD FOR SELECT REPLACE( SUBSTRING( createscript, CHARINDEX('CREATE VIEW', UPPER(createscript)), LEN(createscript) ), 'CREATE VIEW', 'CREATE OR ALTER VIEW' ) AS 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:'; 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;