GO Sau mỗi câu lệnh T-SQL


34

Lý do đằng sau việc sử dụng câu lệnh GO sau mỗi câu lệnh SQL là gì? Tôi hiểu rằng GO báo hiệu kết thúc đợt và / hoặc cho phép danh tiếng của các câu lệnh nhưng nó có lợi thế gì khi sử dụng nó sau mỗi câu lệnh.

Tôi chỉ tò mò vì rất nhiều tài liệu của Microsoft, v.v. đã bắt đầu sử dụng nó sau mỗi tuyên bố hoặc có lẽ tôi mới bắt đầu chú ý.

Ngoài ra những gì được coi là thực hành tốt nhất?

Câu trả lời:


51

Trước khi trả lời khi nào nên sử dụng nó và tại sao, điều đầu tiên là hiểu chính xác GOnó là gì và không phải là gì.

Từ khóa GOđược SQL Server Management Studio và SQLCMD sử dụng để biểu thị một điều và chỉ một điều: Kết thúc một loạt các câu lệnh. Trên thực tế, bạn thậm chí có thể thay đổi những gì bạn sử dụng để chấm dứt các đợt thành một thứ khác ngoài "GO":

nhập mô tả hình ảnh ở đây

Ảnh chụp màn hình ở trên là một tùy chọn trong SSMS có thể định cấu hình.

Nhưng một lô là gì ?? Tài liệu tham khảo BOL này nói rằng nó tốt nhất:

Một lô là một nhóm gồm một hoặc nhiều câu lệnh Transact-SQL được gửi cùng lúc từ một ứng dụng đến SQL Server để thực thi.

Đơn giản như thế. Đó chỉ là một cách tùy chỉnh một ứng dụng (vâng ... một ứng dụng) gửi các câu lệnh đến SQL Server. Chúng ta hãy xem một ví dụ về ứng dụng này. Tôi sẽ sử dụng PowerShell để bắt chước những gì một ứng dụng sẽ làm để gửi các câu lệnh và các đợt tới 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
}

Các ý kiến ​​cho đi, nhưng bạn có thể thấy ở trên rằng chúng tôi đang lập trình gửi hai tới SQL Server. Hãy xác minh rằng, mặc dù. Lựa chọn của tôi ở đây là sử dụng Sự kiện mở rộng:

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

Tất cả phiên XEvents này đang thực hiện là ghi lại các câu lệnh và lô bắt đầu và hoàn thành từ một ứng dụng có tên "BatchTesting"(nếu bạn nhận thấy chuỗi kết nối của tôi trong ví dụ mã PowerShell của tôi, đó là cách nhanh chóng để xem xét một người khởi tạo cụ thể các sự kiện bằng cách sử dụng "ứng dụng" tên "tham số chuỗi kết nối và lọc ra khỏi đó).

Sau khi tôi thực thi mã PowerShell để gửi các lô và báo cáo đó, tôi thấy các kết quả sau:

nhập mô tả hình ảnh ở đây

Như bạn có thể thấy từ ảnh chụp màn hình, rõ ràng cách các câu lệnh được chia thành hai lô khác nhau, cũng được thể hiện rõ bằng các phương tiện chúng ta sử dụng để gọi các đợt. Và nếu chúng ta nhìn vào batch_textlần xuất hiện đầu tiên sql_batch_starting, chúng ta có thể thấy tất cả các câu lệnh được bao gồm trong lô đó:

    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;

Với điều đó giải thích về những gì một lô là, bây giờ đến câu trả lời cho câu hỏi của bạn trong khi chấm dứt lô. Các quy tắc cho các lô được tìm thấy trên tài liệu tham khảo BOL này về các lô :

TẠO DEFAULT, TẠO CHỨC NĂNG, TẠO QUY TRÌNH, TẠO QUY TẮC, TẠO SCHema, TẠO TRIGGER và TẠO VIEW có thể được kết hợp với các câu lệnh khác trong một đợt. Câu lệnh CREATE phải bắt đầu lô. Tất cả các câu lệnh khác theo sau trong đợt đó sẽ được hiểu là một phần của định nghĩa của câu lệnh CREATE đầu tiên.

Một bảng không thể thay đổi và sau đó các cột mới được tham chiếu trong cùng một lô.

Nếu một câu lệnh EXECUTE là câu lệnh đầu tiên trong một đợt, thì từ khóa EXECUTE là không bắt buộc. Từ khóa EXECUTE là bắt buộc nếu câu lệnh EXECUTE không phải là câu lệnh đầu tiên trong lô.

Tương tự, một số lỗi thời gian chạy (lỗi biên dịch sẽ không cho phép thực thi một đợt bắt đầu) xảy ra trong một đợt có thể gây ra các hành vi khác nhau: hủy bỏ toàn bộ lô hoặc tiếp tục lô và chỉ hủy bỏ câu lệnh vi phạm (ở trên liên kết đưa ra hai ví dụ thực sự tốt: Chẳng hạn, lỗi tràn số học sẽ dừng việc thực thi lô, trong khi đó lỗi vi phạm ràng buộc sẽ chỉ ngăn câu lệnh hiện tại hoàn thành nhưng lô sẽ tiếp tục thực thi).

Tuy nhiên, giống như nhiều thứ trong nghề nghiệp của chúng tôi, sở thích cá nhân sẽ là một động lực rất lớn đằng sau cách bạn với tư cách là một cá nhân và người viết mã T-SQL chấm dứt các lô. Một số người chỉ xác định rõ ràng các lô khi họ thực sự phải (xem ở trên đối với các yêu cầu đó) và những người khác chấm dứt các lô theo chương trình 100% thời gian , ngay cả khi họ chỉ thực hiện một câu lệnh trong Cửa sổ truy vấn trong SSMS. Hầu hết mọi người thường rơi ở đâu đó ở giữa hai ranh giới đó. Đối với những gì nó có giá trị, các bộ kết thúc câu lệnh có cùng một điều với rất ít yêu cầu được thi hành. Một phần lớn của tất cả những điều này là kiểu mã , trong đó nó không được thi hành (trong SSMS và SQLCMD).


Có lẽ là một nhận xét ngây thơ nhưng nó gây ấn tượng với tôi rằng SQL Server có thể đã xác định những gì sẽ chạy theo lô (theo cách tương tự như nhiều tối ưu hóa khác được xử lý bởi công cụ cơ sở dữ liệu). Ví dụ: sử dụng các quy tắc bạn đã mô tả thay vì dựa vào người dùng để tạo tập lệnh cho họ, điều này có thể dễ bị lỗi và dường như thêm sự phình to không cần thiết vào tập lệnh.
Steve Chambers

1
@SteveChambers chính xác tình cảm của tôi. Câu trả lời cho biết "nó đơn giản như vậy" (Một lô là một nhóm gồm một hoặc nhiều câu lệnh Transact-SQL được gửi cùng lúc từ một ứng dụng đến SQL Server để thực thi.) Nhưng không phải vậy. Có những kết hợp các câu lệnh tôi có thể thử và gửi trong một đợt không thành công. Cuối cùng tôi nghĩ bạn cần phải hiểu tại saocách gửi một đợt khác với gửi một tập hợp các câu lệnh riêng lẻ - vì vậy cuối cùng tôi đã đóng góp câu trả lời của riêng mình cho câu hỏi này: stackoverflow.com/a/56370223/3714936 - cũng nói lên nhận xét của bạn .
youcantryreachingme
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.