GO 모든 T-SQL 문 이후


34

모든 SQL 문 다음에 GO 문을 사용하는 이유는 무엇입니까? GO는 일괄 처리의 끝을 알리고 / 또는 진술의 명성을 허용하지만 모든 진술 후에 그것을 사용하면 어떤 이점이 있습니까?

모든 진술 후에 많은 Microsoft 문서 등이 그것을 사용하기 시작했거나 방금 주목하기 시작했을 때 궁금합니다.

가장 좋은 방법은 무엇입니까?

답변:


51

사용시기와 이유에 대답하기 전에 정확히 무엇이 무엇 GO이고 무엇이 아닌지 를 이해하는 것이 가장 중요 합니다.

이 키워드 GO는 SQL Server Management Studio 및 SQLCMD에서 한 가지만, 한 가지만 나타 내기 위해 사용됩니다. 실제로 배치를 종료하기 위해 사용하는 것을 "GO"이외의 것으로 변경할 수도 있습니다 .

여기에 이미지 설명을 입력하십시오

위의 스크린 샷은 구성 가능한 SSMS 내의 옵션입니다.

그러나 배치는 무엇입니까 ?? 이 BOL 참조 는 가장 잘 말합니다.

일괄 처리는 응용 프로그램에서 SQL Server로 동시에 전송되어 실행되는 하나 이상의 Transact-SQL 문의 그룹입니다 .

그렇게 간단합니다. 응용 프로그램 (예 ... 응용 프로그램)이 SQL Server에 문을 보내는 사용자 지정 방식입니다. 이에 대한 응용 프로그램 예를 살펴 보겠습니다. PowerShell을 사용하여 응용 프로그램이 명령문 및 배치를 SQL Server로 전송하기 위해 수행 할 작업을 모방합니다.

$ConnectionString = "data source = SomeSQLInstance; initial catalog = AdventureWorks2012; trusted_connection = true; application name = BatchTesting;"

try {
    $SqlConnection = New-Object System.Data.SqlClient.SqlConnection($ConnectionString)
    $SqlCmd = New-Object System.Data.SqlClient.SqlCommand
    $SqlCmd.Connection = $SqlConnection

    # first batch of statements
    #
    $SqlCmd.CommandText = "
        select * from humanresources.department where departmentid = 1;
        select * from humanresources.department where departmentid = 2;
        select * from humanresources.department where departmentid = 3;
        select * from humanresources.department where departmentid = 4;"

    # execute the first batch
    #
    $SqlConnection.Open()
    $SqlCmd.ExecuteNonQuery()
    $SqlConnection.Close()

    # second batch of statements
    #
    $SqlCmd.CommandText = "
        select * from humanresources.department where departmentid = 5;
        select * from humanresources.department where departmentid = 6;
        select * from humanresources.department where departmentid = 7;
        select * from humanresources.department where departmentid = 8;"

    # execute the second batch
    #
    $SqlConnection.Open()
    $SqlCmd.ExecuteNonQuery()
    $SqlConnection.Close()
}
catch {
    $SqlCmd.Dispose()
    $SqlConnection.Dispose()
    Write-Error $_.Exception
}

주석은 그 내용을 알려주지 만, 위와 같이 프로그래밍 방식으로 두 개의 배치 를 SQL Server에 보내는 것을 볼 수 있습니다 . 그래도 확인합시다. 여기서 선택한 것은 확장 이벤트를 사용하는 것입니다.

create event session BatchTesting
on server
add event sqlserver.sql_batch_starting
(
    set
        collect_batch_text = 1
    where
    (
        sqlserver.client_app_name = N'BatchTesting'
    )
),
add event sqlserver.sql_batch_completed
(
    set
        collect_batch_text = 1
    where
    (
        sqlserver.client_app_name = N'BatchTesting'
    )
),
add event sqlserver.sql_statement_starting
(
    set
        collect_statement = 1
    where
    (
        sqlserver.client_app_name = N'BatchTesting'
    )
),
add event sqlserver.sql_statement_completed
(
    set
        collect_statement = 1
    where
    (
        sqlserver.client_app_name = N'BatchTesting'
    )
)
add target package0.event_file
(
    set
        filename = N'<MyXelLocation>\BatchTesting.xel'
);
go

alter event session BatchTesting
on server
state = start;
go

이 XEvents 세션이 수행하는 모든 작업은 이름이 지정된 응용 프로그램에서 시작 및 완료되는 명령문과 배치를 캡처하는 것입니다 (Python "BatchTesting"코드 예제에서 연결 문자열이 표시되는 경우 "application name "연결 문자열 매개 변수 및 필터링).

PowerShell 코드를 실행하여 해당 일괄 처리 및 문을 보내면 다음 결과가 나타납니다.

여기에 이미지 설명을 입력하십시오

스크린 샷에서 볼 수 있듯이 명령문을 두 개의 다른 배치로 나누는 방법이 분명합니다. 또한 배치를 호출하는 데 사용한 방법에 의해 분명합니다. 그리고 batch_text의 첫 번째 항목을 살펴보면 sql_batch_starting해당 배치에 포함 된 모든 명령문을 볼 수 있습니다.

    select * from humanresources.department where departmentid = 1;
    select * from humanresources.department where departmentid = 2;
    select * from humanresources.department where departmentid = 3;
    select * from humanresources.department where departmentid = 4;

배치가 무엇인지에 대한 설명과 함께 배치 종료 시기 에 대한 귀하의 질문에 대한 답변이 제공 됩니다 . 배치에 대한 규칙은 배치 와 관련하여이 BOL 참조 에서 찾을 수 있습니다 .

CREATE DEFAULT, CREATE FUNCTION, CREATE PROCEDURE, CREATE RULE, CREATE SCHEMA, CREATE TRIGGER 및 CREATE VIEW 문은 일괄 적으로 다른 명령문과 결합 할 수 없습니다. CREATE 문은 배치를 시작해야합니다. 해당 배치에서 뒤 따르는 다른 모든 명령문은 첫 번째 CREATE 문 정의의 일부로 해석됩니다.

테이블을 변경할 수없고 동일한 열에서 새 열이 참조됩니다.

EXECUTE 문이 일괄 처리의 첫 번째 명령문 인 경우 EXECUTE 키워드가 필요하지 않습니다. EXECUTE 문이 일괄 처리의 첫 번째 명령문이 아닌 경우 EXECUTE 키워드가 필요합니다.

마찬가지로, 배치 중에 발생하는 특정 런타임 오류 (컴파일 오류로 인해 배치 실행을 시작할 수 없음)에 따라 다른 동작이 발생할 수 있습니다. 예를 들어 산술 오버플로 오류는 배치 실행을 중지하지만 제약 조건 위반 오류는 현재 명령문의 완료를 막지 만 배치는 계속 실행합니다).

그러나 우리 직업의 많은 것들과 마찬가지로 개인 선호도 는 개인 및 T-SQL 코드 작성자로서 배치를 종료하는 방법에 큰 원동력이 될 것입니다. 어떤 사람들 은 반드시 배치를 명시 적으로 정의 해야하고 (이러한 요구 사항에 대해서는 위를 참조하십시오), 다른 사람들 은 SSMS의 쿼리 창에서 단일 명령문 만 실행하더라도 프로그래밍 방식으로 배치를 100 % 종료합니다 . 대부분의 사람들은 일반적으로이 두 경계의 한가운데에 빠집니다. 가치가있는 것에 대해, 명령문 종결자는 강제 요구 사항도 거의없이 동일합니다. 이 모든 것의 큰 부분은 SSMS 및 SQLCMD에서 적용되지 않는 코드 스타일 입니다.


아마도 순진한 의견이지만 SQL Server가 배치 자체로 실행할 항목을 결정할 수 있다는 사실에 놀랐습니다 (데이터베이스 엔진이 다른 많은 최적화를 처리하는 것과 동일한 방식으로). 예를 들어 설명한 규칙을 사용하여 스크립트를 작성하는 대신 사용자가 설명한 규칙을 사용하면 오류가 발생하기 쉽고 스크립트에 불필요한 팽창이 추가되는 것 같습니다.
Steve Chambers

1
@SteveChambers 내 정서를 정확하게. 대답은 "그것만큼 간단합니다"라고 말합니다 (일괄 처리는 실행을 위해 응용 프로그램에서 SQL Server로 동시에 전송되는 하나 이상의 Transact-SQL 문 그룹입니다). 실패한 배치로 시도하고 보낼 수있는 명령문 조합이 있습니다. 궁극적으로 당신이 이해할 필요가 있다고 생각 하는 이유방법 : 내가 마지막으로이 일에 내 자신의 대답을 기여 있도록 - 배치를 보내는 개별 문장의 집합을 보내는 것보다 다른 stackoverflow.com/a/56370223/3714936 - 또한 귀하의 코멘트에 말을 .
youcantryreachingme
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.