Additional SQL Server features and topics not covered by specific categories
Why the error happens ("Must declare the scalar variable...")
You are correct that enabling CDC creates a database-level DDL trigger (tr_MScdc_ddl_event). However, your theory about the "failure to interpret the DDL trigger's SQL" is slightly off. The trigger itself compiles perfectly.
The failure happens because of scope isolation:
An ALTER INDEX statement counts as a Data Definition Language (DDL) command. When your maintenance script executes ALTER INDEX, the synchronous CDC DDL trigger fires. SQL Server executes DDL triggers in a separate, internal batch scope. Because local scalar variables (like @number) are strictly isolated to the exact batch where they are declared, the separate execution scope forced by the trigger cannot "see" your @number variable. When the trigger captures the event data, the parent statement fails parsing in that nested scope, resulting in the runtime error and aborting your transaction.
Feedback on Your Solutions
Review of Solution 1: Temporarily disable CDC
- Critical Warning: Avoid using
sys.sp_cdc_disable_dborsys.sp_cdc_disable_table. Disabling CDC at the database or table level will completely drop your tracking tables (_CT) and delete all captured historical data. When you turn it back on, it starts fresh, losing everything you wanted to migrate. - The Nuance: If you meant pausing the CDC SQL Server Agent capture jobs, that will not work either. The jobs only process DML (INSERT/UPDATE); pausing them does not disable the synchronous DDL trigger.
Review of Solution 2: Disable DDL triggers during the migration period
- Assessment: This is a highly effective, standard infrastructure-level workaround for migration maintenance windows.
- Your Caveat Check: You are completely correct. As long as no structural changes to table definitions (like
ALTER TABLEadding/dropping columns) are performed while the trigger is disabled, no tracking data or schema history will be missed. Index rebuilding does not alter tracked column structures, making it safe.
You may try following fix:
Option A: Cleanly Toggle the Specific Trigger (Fastest Infrastructure Fix)
Instead of touching CDC itself, disable and re-enable only the specific DDL trigger causing the scope break at the beginning and end of your maintenance batch:
-- 1. Disable the specific CDC DDL trigger before running index maintenance
DISABLE TRIGGER tr_MScdc_ddl_event ON DATABASE;
-- 2. Run your index rebuild/maintenance batch here
-- (The @number variable will no longer trigger a scope fault)
-- 3. IMMEDIATELY re-enable the trigger once maintenance completes
ENABLE TRIGGER tr_MScdc_ddl_event ON DATABASE;
Option B: Fix the Maintenance Script's Dynamic SQL
If you can edit the maintenance script code, modify the ALTER INDEX logic to either inline the scalar value using string concatenation or safely pass the variable scope using sp_executesql: sql
-- Fix Example using parameterized execution:
SET @sql = N'ALTER INDEX ALL ON MyTable REBUILD WITH (MAXDOP = @number)';
EXEC sp_executesql @sql, N'@number INT', @number = @number;