213 lines
7.3 KiB
Transact-SQL
213 lines
7.3 KiB
Transact-SQL
-- ======================================================
|
|
-- 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';
|
|
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;
|
|
FETCH NEXT FROM colCur INTO @Schema, @Table, @Column, @OldDataType, @IsNullable;
|
|
|
|
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;
|
|
-- 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;
|
|
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 FAST_FORWARD FOR
|
|
SELECT createscript, ViewFullName
|
|
FROM SchemaBoundViews ;
|
|
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:';
|
|
|
|
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;
|
|
|