批處理簡介
批處理是作為一個邏輯單元的T-SQL語句。如果一條語句不能通過語法分析,那么不會運行任何語句。如果一條語句在運行時失敗,那么產生錯誤的語句之前的語句都已經運行了。
為了將一個腳本分為多個批處理,可使用GO語句。
GO語句的特點:
- GO語句必須自成一行,只有注釋可以再同一行上。
- 它使得自腳本的開始部分或者最近一個GO語句以后的所有語句編譯成一個執行計划並發送到服務器,與任何其他批處理無關。
- GO語句不是T-SQL命令,而是由各種SQL Server命令實用程序(如:Management Studio中的"查詢"窗口)識別的命令。
1、自成一行
GO命令應當自成一行。在技術上,可以在GO命令之后的同一行開始一個新的批處理,但是這會嚴重影響可讀性。T-SQL語句不能放在GO語句之前,否則GO語句經常會被錯誤地理解,從而造成語法分析錯誤或產生一些不可預料的后果。例如,在WHERE子句之后使用一個GO語句。
SELECT * FROM Person WHERE Id = 100 GO
分析器就不知道如何處理。
消息 102,級別 15,狀態 1,第 1 行
'GO' 附近有語法錯誤。
2、每個批處理單獨發送到服務器
因為每個批處理被單獨地處理,所以一個批處理中的錯誤不會阻止另一個批處理運行。要說明這點,請看一下下面的代碼。
SELECT 1/0 GO SELECT 0/1
如果這些批處理之間沒有任何依賴性,則每個批處理在運行時是完全自治的。
消息 8134,級別 16,狀態 1,第 1 行 遇到以零作除數錯誤。 (1 行受影響)
如果這些批處理之間存在依賴性,那么錯誤發生之后的每個批處理都會失敗。依賴性指的是后面的語句,依賴前面執行的結果或變量等等。
3、GO不是T-SQL命令
一個常見的錯誤是認為GO是T-SQL命令,其實GO是一個只能被編輯工具(Management Studio)識別的命令。
當編輯工具遇到GO語句時,會將GO語句看做一個終止批處理的標記,將其打包,並且作為一個獨立的單元發送到服務器,不包括GO。因為服務器本身根本不知道GO是什么意思。
批處理中錯誤
批處理中的錯誤分為以下兩類:
- 語法錯誤
- 運行時錯誤
如果查詢分析器發現一個語法錯誤,那么批處理的處理過程會被立即取消。因為語法檢查發生在批處理編譯或者執行之前,所以在語法檢查期間的一個失敗意味着還沒有批處理被執行-不管語法錯誤發生在批處理中的什么位置。
運行時錯誤的工作方式有很大不同,因為任何在遇到運行時錯誤之前執行的語句已經完成了,所以除非是未提交事務的一部分,否則這些語句所做的任何事情都已經是現實了。
一般而言,運行時錯誤將終止從錯誤發生的地方到此批處理末端的批處理的執行。下一個批處理不影響。
何時使用批處理
使用批處理有若干個理由,但是所有的批處理都有一個共同點-當腳本中的一些事情必須發生在另外一件事情之前或者分開發生時,需要使用批處理。
1.要求有自己的批處理的語句
有一些命令必須有他們自己的批處理。
- CREATE DEFAULT
- CREATE PROCEDURE
- CREATE RULE
- CREATE TRIGGER
- CREATE VIEW
如果想在單個腳本中將這些語句中的任意一個和其他語句進行組合,那么需要通過使用GO語句將他們分散到各自的批處理中。
2、使用批處理建立優先權
當需要建立優先權時,就可能用到批處理。也就是說,在下一個任務開始之前,需要全部完成上一個任務。在大多數時候,SQL Server可以很好地處理這種情況 - 腳本中的第一條語句是首先執行的,並且腳本中的第二條語句可以依賴第二條語句運行時服務器所處的適當狀態。
下面來看一個例子:
USE master CREATE DATABASE Test CREATE TABLE TestTable ( col1 int, col2 int )
當執行上面的腳本,提示命令已成功完成。但是真的沒問題嗎?
當查看Test數據庫時,發現表TestTable並不存在,反而master數據庫里多了一個TestTable表。
為什么表被創建在了master數據庫中,答案取決於當運行CREATE TABLE語句時,當前數據庫是什么。在這個例子中,它恰好是master數據庫,所以表就創建在該數據庫中。
你可能以為將上述代碼改成這樣可能就能夠解決:
CREATE DATABASE Test USE Test CREATE TABLE TestTable ( col1 int, col2 int )
但很遺憾,並不能,錯誤信息如下:
消息 911,級別 16,狀態 1,第 3 行
數據庫 'Test' 不存在。請確保正確地輸入了該名稱。
分析器嘗試驗證代碼時,發現USE引用一個不存在的數據庫,這是批處理語句不可或缺,正確的代碼如下:
CREATE DATABASE Test GO --此GO是兩主角 USE Test CREATE TABLE TestTable ( col1 int, col2 int )
就這樣加了一個GO之后,問題成功解決。
下面再來看一個例子:
USE Test ALTER TABLE TestTable ADD col3 int INSERT INTO TestTable (col1,col2,col3) VALUES (1,1,1)
以上代碼在查詢分析器中提示col3列不存在。實際上,以上代碼也可以通過一個GO解決。
USE Test ALTER TABLE TestTable ADD col3 int GO --先更改數據庫,然發送插入,此時就是分開進行語法驗證了 INSERT INTO TestTable (col1,col2,col3) VALUES (1,1,1)