TSQL - How to use GO inside of a BEGIN .. END block?

后端 未结 8 871
一生所求
一生所求 2020-12-02 18:06

I am generating a script for automatically migrating changes from multiple development databases to staging/production. Basically, it takes a bunch of change-scripts, and m

相关标签:
8条回答
  • 2020-12-02 18:23

    You could try sp_executesql, splitting the contents between each GO statement into a separate string to be executed, as demonstrated in the example below. Also, there is a @statementNo variable to track which statement is being executed for easy debugging where an exception occurred. The line numbers will be relative to the beginning of the relevant statement number that caused the error.

    BEGIN TRAN
    
    DECLARE @statementNo INT
    BEGIN TRY
        IF 1=1
        BEGIN
            SET @statementNo = 1
            EXEC sp_executesql
                N'  ALTER TABLE dbo.EMPLOYEE
                        ADD COLUMN EMP_IS_ADMIN BIT NOT NULL'
    
            SET @statementNo = 2
            EXEC sp_executesql
                N'  UPDATE dbo.EMPLOYEE
                        SET EMP_IS_ADMIN = 1'
    
            SET @statementNo = 3
            EXEC sp_executesql
                N'  UPDATE dbo.EMPLOYEE
                        SET EMP_IS_ADMIN = 1x'
        END
    END TRY
    BEGIN CATCH
        PRINT 'Error occurred on line ' + cast(ERROR_LINE() as varchar(10)) 
           + ' of ' + 'statement # ' + cast(@statementNo as varchar(10)) 
           + ': ' + ERROR_MESSAGE()
        -- error occurred, so rollback the transaction
        ROLLBACK
    END CATCH
    -- if we were successful, we should still have a transaction, so commit it
    IF @@TRANCOUNT > 0
        COMMIT
    

    You can also easily execute multi-line statements, as demonstrated in the example above, by simply wrapping them in single quotes ('). Don't forget to escape any single quotes contained inside the string with a double single-quote ('') when generating the scripts.

    0 讨论(0)
  • 2020-12-02 18:33

    I ultimately got it to work by replacing every instance of GO on its own line with

    END
    GO
    
    ---Automatic replacement of GO keyword, need to recheck IF conditional:
    IF whatever
    BEGIN
    

    This is greatly preferable to wrapping every group of statements in a string, but is still far from ideal. If anyone finds a better solution, post it and I'll accept it instead.

    0 讨论(0)
  • 2020-12-02 18:38

    I have used RAISERROR in the past for this

    IF NOT whatever BEGIN
        RAISERROR('YOU''RE ALL SET, and sorry for the error!', 20, -1) WITH LOG
    END
    
    ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
    GO
    UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever
    
    0 讨论(0)
  • 2020-12-02 18:39

    You can enclose the statements in BEGIN and END instead of the GO inbetween

    IF COL_LENGTH('Employees','EMP_IS_ADMIN') IS NULL --Column does not exist
    BEGIN
        BEGIN
            ALTER TABLE dbo.Employees ADD EMP_IS_ADMIN BIT
        END
    
        BEGIN
            UPDATE EMPLOYEES SET EMP_IS_ADMIN = 0
        END
    END
    

    (Tested on Northwind database)

    Edit: (Probably tested on SQL2012)

    0 讨论(0)
  • 2020-12-02 18:39

    You may try this solution:

    if exists(
    SELECT...
    )
    BEGIN
    PRINT 'NOT RUN'
    RETURN
    END
    
    --if upper code not true
    
    ALTER...
    GO
    UPDATE...
    GO
    
    0 讨论(0)
  • 2020-12-02 18:42

    GO is not SQL - it is simply a batch separator used in some MS SQL tools.

    If you don't use that, you need to ensure the statements are executed separately - either in different batches or by using dynamic SQL for the population (thanks @gbn):

    IF whatever
    BEGIN
        ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL;
    
        EXEC ('UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever')
    END
    
    0 讨论(0)
提交回复
热议问题