GO 在每個 T-SQL 語句之後
在每個 SQL 語句之後使用 GO 語句的原因是什麼?我知道 GO 表示批處理的結束和/或允許語句的聲譽,但是在每個語句之後使用它有什麼優勢。
我只是好奇,因為很多 Microsoft 文件等在每個聲明之後都開始使用它,或者我剛剛開始注意到。
還有什麼被認為是最佳實踐?
在回答何時使用它以及為什麼使用它之前,首先要準確了解什麼
GO
是什麼,什麼不是。SQL Server Management Studio 和 SQLCMD 使用該關鍵字
GO
來表示一件事且只有一件事:一批語句的結束。事實上,您甚至可以將用於終止批處理的內容更改為“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 會話所做的就是擷取從名為的應用程序開始和完成的語句和批處理
"BatchTesting"
(如果您在我的 PowerShell 程式碼範例中註意到我的連接字元串,這是一種使用“應用程序”來查看特定事件發起者的快速方法名稱”連接字元串參數並過濾掉它)。在執行 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 程式碼編寫者如何終止批處理的巨大驅動力。有些人只在絕對必要時才顯式定義批處理(有關這些要求,請參見上文),而其他人 100% 的時間以程式方式終止批處理,即使他們只在 SSMS 的查詢視窗中執行單個語句。大多數人通常落在這兩個邊界的中間。就其價值而言,語句終止符具有相同的追隨者,而且強制要求也很少。所有這一切的很大一部分是程式碼樣式,它沒有被強制執行(在 SSMS 和 SQLCMD 中)。