ป้ายกำกับ: Batch

MSSQL: Batch Alter Table Drop ColumnsMSSQL: Batch Alter Table Drop Columns

ตัวอย่าง batch script alter drop column หลาย ๆ column ออกจาก table ในครั้งเดียว และ
batch_alter_table_drop_columns.sql

-- USE DB_DEV;
-- USE DB_QA;
-- USE DB_SIT;
-- USE DB_PRO;

-- 1. Configuration
DECLARE @SchemaName AS NVARCHAR(128) = N'PItt';
DECLARE @TableName AS NVARCHAR(128) = N'Phunsanit';

-- 2. stop scrip if column not null and empty
DECLARE @StopScript BIT = 0; -- flag to stop the script

-- 3. Variables for the script
DECLARE @FullTableName NVARCHAR(257);
DECLARE @TableObjectID INT;
DECLARE @CurrentColumnName NVARCHAR(128);
DECLARE @SqlStatement NVARCHAR(MAX);
DECLARE @HasData BIT = 0;
DECLARE @CheckSql NVARCHAR(MAX);
DECLARE @CheckParams NVARCHAR(100) = N'@HasData BIT OUTPUT';
DECLARE @DataTypeName NVARCHAR(128); -- <-- NEW: To store the column's data type

-- 4. Define the list of columns you want to drop
DECLARE @ColumnsToDrop TABLE (
 ColumnName NVARCHAR(128) PRIMARY KEY
);

INSERT INTO @ColumnsToDrop (ColumnName)
VALUES
 (N'created_at'),
 (N'created_by'),
 (N'deleted_at'),
 (N'deleted_by'),
 (N'updated_at'),
 (N'updated_by'),

-- 5. Store the actual commands to run (if checks pass)
DECLARE @CommandsToRun TABLE (
 SqlStatement NVARCHAR(MAX),
 ColumnName NVARCHAR(128)
);

-- 6. Safety Check: Stop if the table itself doesn't exist
SET @FullTableName = QUOTENAME(@SchemaName) + '.' + QUOTENAME(@TableName);
SET @TableObjectID = OBJECT_ID(@FullTableName);

IF @TableObjectID IS NULL
BEGIN
 PRINT 'Error: The table ' + @FullTableName + ' does not exist. Halting script.';
 RETURN; -- Stops the script
END

PRINT '--- PRE-CHECK ---';
PRINT 'Checking columns on table: ' + @FullTableName;

-- 7. Create a cursor to loop through and check each column
DECLARE col_cursor CURSOR FOR
SELECT ColumnName FROM @ColumnsToDrop;

OPEN col_cursor;

FETCH NEXT FROM col_cursor INTO @CurrentColumnName;

-- 8. First Loop (Pre-Check)
WHILE @@FETCH_STATUS = 0
BEGIN
 SET @HasData = 0; -- Reset flag for each column

 -- Check if the column exists on this specific table
 IF EXISTS (SELECT 1
    FROM sys.columns c
    WHERE c.object_id = @TableObjectID
     AND c.name = @CurrentColumnName)
 BEGIN

  -- *** MODIFIED BLOCK ***
  -- First, get the column's data type
  SELECT @DataTypeName = ty.name
  FROM sys.columns c
  JOIN sys.types ty ON c.user_type_id = ty.user_type_id
  WHERE c.object_id = @TableObjectID
   AND c.name = @CurrentColumnName;

  -- Now build the data check SQL based on the type
  IF @DataTypeName IN (N'varchar', N'nvarchar', N'char', N'nchar', N'text', N'ntext')
  BEGIN
   -- For string types, check for NOT NULL AND not empty string (your request)
   -- This means NULLs or '' (empty strings) are OK to drop
   SET @CheckSql = N'SELECT TOP 1 @HasData = 1 FROM ' + @FullTableName +
       N' WHERE ' + QUOTENAME(@CurrentColumnName) + N' IS NOT NULL' +
       N' AND ' + QUOTENAME(@CurrentColumnName) + N' != '''''; -- '''' is an escaped '
   PRINT ' [INFO] Column ' + QUOTENAME(@CurrentColumnName) + ' is a string. Checking for data (not NULL and not '''').';
  END
  ELSE
  BEGIN
   -- For non-string types (int, datetime, etc.), just check for NOT NULL
   SET @CheckSql = N'SELECT TOP 1 @HasData = 1 FROM ' + @FullTableName +
       N' WHERE ' + QUOTENAME(@CurrentColumnName) + N' IS NOT NULL';
   PRINT ' [INFO] Column ' + QUOTENAME(@CurrentColumnName) + ' is not a string. Checking for data (not NULL).';
  END

  -- Run the dynamic check
  EXEC sp_executesql @CheckSql, @CheckParams, @HasData = @HasData OUTPUT;
  -- *** END OF MODIFIED BLOCK ***

  IF @HasData = 1
  BEGIN
   -- Data found! Mark the script to stop.
   PRINT ' [ERROR] Column ' + QUOTENAME(@CurrentColumnName) + ' contains data. Script will be stopped.';
   SET @StopScript = 1;
  END
  ELSE
  BEGIN
   -- Column is empty (all NULL or ''). It is safe to drop.
   PRINT ' [OK] Column ' + QUOTENAME(@CurrentColumnName) + ' is empty. Queued for drop.';

   -- Add the drop command to our queue
   SET @SqlStatement = N'ALTER TABLE ' + @FullTableName +
        N' DROP COLUMN ' + QUOTENAME(@CurrentColumnName);
   INSERT INTO @CommandsToRun (SqlStatement, ColumnName)
   VALUES (@SqlStatement, @CurrentColumnName);
  END
 END
 ELSE
 BEGIN
  -- Column does not exist, so skip it
  PRINT ' [INFO] Column ' + QUOTENAME(@CurrentColumnName) + ' (does not exist). Skipping.';
 END

 -- Get the next column from the list
 FETCH NEXT FROM col_cursor INTO @CurrentColumnName;
END;

-- 9. Clean up the check cursor
CLOSE col_cursor;
DEALLOCATE col_cursor;

-- 10. THE "STOP" CHECK
PRINT '---';
IF @StopScript = 1
BEGIN
 PRINT 'Execution HALTED. One or more columns contained data (see [ERROR] messages above).';
 PRINT 'No columns were dropped.';
 RETURN; -- This is the STOP you requested
END

-- 11. Execution (only runs if @StopScript is still 0)
PRINT 'All checks passed. Proceeding with drop operations...';

DECLARE exec_cursor CURSOR FOR
SELECT SqlStatement, ColumnName FROM @CommandsToRun;

OPEN exec_cursor;

FETCH NEXT FROM exec_cursor INTO @SqlStatement, @CurrentColumnName;

WHILE @@FETCH_STATUS = 0
BEGIN
 BEGIN TRY
  EXEC sp_executesql @SqlStatement;
  PRINT ' Successfully dropped column: ' + QUOTENAME(@CurrentColumnName);
 END TRY
 BEGIN CATCH
  PRINT ' ERROR: Could not drop column ' + QUOTENAME(@CurrentColumnName) + '. Please check dependencies (indexes, constraints).';
  PRINT ' Error Message: ' + ERROR_MESSAGE();
 END CATCH

 FETCH NEXT FROM exec_cursor INTO @SqlStatement, @CurrentColumnName;
END;

-- 12. Clean up the execution cursor
CLOSE exec_cursor;
DEALLOCATE exec_cursor;

PRINT 'Column drop process complete.';