program story

TSQL-BEGIN .. END 블록 내에서 GO를 사용하는 방법?

inputbox 2020. 9. 8. 07:55
반응형

TSQL-BEGIN .. END 블록 내에서 GO를 사용하는 방법?


여러 개발 데이터베이스의 변경 사항을 스테이징 / 프로덕션으로 자동 마이그레이션하는 스크립트를 생성하고 있습니다. 기본적으로 많은 변경 스크립트를 사용하여 단일 스크립트로 병합하여 각 스크립트를 IF whatever BEGIN ... END명령문으로 래핑 합니다.

그러나 일부 스크립트에는 GO예를 들어 SQL 파서가 새 열이 생성 된 후 새 열에 대해 알 수 있도록 문이 필요합니다 .

ALTER TABLE dbo.EMPLOYEE 
ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
GO -- Necessary, or next line will generate "Unknown column:  EMP_IS_ADMIN"
UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever

그러나 일단 IF블록으로 감싸면 다음과 같습니다.

IF whatever
BEGIN
    ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
    GO
    UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever
END

BEGIN일치하지 않는를 보내고 있기 때문에 실패합니다 END. 그러나 내가 제거 GO하면 알 수없는 열에 대해 다시 불평합니다.

단일 IF블록 내에서 동일한 열을 만들고 업데이트하는 방법이 있습니까?


GO SQL이 아닙니다. 일부 MS SQL 도구에서 사용되는 배치 구분 기호 일뿐입니다.

이를 사용하지 않는 경우 다른 배치로 또는 모집단에 대한 동적 SQL을 사용하여 문이 별도로 실행되는지 확인해야합니다 (@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

나는 같은 문제가 있었고 마침내 SET NOEXEC를 사용하여 해결했습니다 .

IF not whatever
BEGIN
    SET NOEXEC ON; 
END

ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
GO
UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever

SET NOEXEC OFF; 

당신은 시도해 볼 수도 있습니다 sp_executesql각각의 내용을 분할, GO아래 예제와 같이 별도의 문자열로 문을 실행 할 수 있습니다. 또한 예외가 발생한 위치를 쉽게 디버깅 할 수 있도록 실행중인 문을 추적하는 @statementNo 변수가 있습니다. 줄 번호는 오류를 일으킨 관련 명령문 번호의 시작 부분을 기준으로합니다.

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.


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.


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)


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

You may try this solution:

if exists(
SELECT...
)
BEGIN
PRINT 'NOT RUN'
RETURN
END

--if upper code not true

ALTER...
GO
UPDATE...
GO

You can incorporate a GOTO and LABEL statements to skip over code, thus leaving the GO keywords intact.

참고URL : https://stackoverflow.com/questions/6376866/tsql-how-to-use-go-inside-of-a-begin-end-block

반응형