Search code examples
sql-serversql-server-2014

Running SQL in one transaction has different results to running separately


I can't work out why this is the case, but if I run:

BEGIN TRANSACTION
    ALTER TABLE [TABLE NAME] DISABLE TRIGGER [TRIGGER NAME];

    -- Some query

    ALTER TABLE [TABLE NAME] ENABLE TRIGGER [TRIGGER NAME];
COMMIT TRANSACTION

Where 'some query' depends on the trigger being disabled, I get an error (since the trigger hasn't successfully been disabled).

However, if I run the alter statements separately, it's fine.

I've tried DISABLE TRIGGER syntax instead, and I've tried BEGIN and END instead of BEGIN TRANSACTIONetc.

What am I misunderstanding here? Why do these alter statements not appear to alter 'in time'?

EDIT

I'd like to rephrase the question in favour of clarity to accompany the bounty:

Why must we separate batches of DDL and DML?


Solution

  • Since you are executing them in the same batch/statement, you are altering table AFTER sql server has compiled your sql statement.

    1. SQL Server compiles your statement (including all the individual DDL and DML commands in the batch)
    2. SQL Server alters your TABLE to disable trigger
    3. SQL Server runs your "query", but it is compiled to assume there was a trigger there, so the trigger runs.
    4. SQL Server alters your TABLE to enable trigger

    To solve this, you can still do it within a transaction, but you will need to separate into batches. Insert "GO" between each statement if running from SSMS or similar tool, or call individual SQL statement if calling from code.