2011-10-25

使用 GO 命令來多次執行 T-SQL 批次

適用版本:
SQL Server 2005、SQL Server 2008、SQL Server 2008 R2。

但 SQL Server 2000 不支援使用 GO 命令搭配引數 count。

GO (Transact-SQL) :作為 SQL Server 公用程式中 Transact-SQL 陳述式批次結束的信號。

語法:
GO [count]

引數:
count:這是正整數。在 GO 之前的批次將會執行指定的次數。



請參考以下的範例程式碼:

使用環境:
SQL Server 2008 R2。

--00 建立範例資料表:tbGO1、tbGO2
USE tempdb
GO
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[tbGO1]') AND type in (N'U'))
DROP TABLE [dbo].[tbGO1]
GO
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[tbGO2]') AND type in (N'U'))
DROP TABLE [dbo].[tbGO2]
GO
CREATE TABLE dbo.tbGO1
(rid int IDENTITY, myDatetime2 datetime2)
GO
CREATE TABLE dbo.tbGO2
(rid int IDENTITY, myGUID uniqueidentifier)
GO

--01 在 GO 之前的批次將會執行 2 次。
INSERT tempdb.dbo.tbGO1 VALUES(SYSDATETIME());
INSERT tempdb.dbo.tbGO2 VALUES(NEWID());
GO 2

--02 在 GO 之前的批次將會執行 100 次。
SET NOCOUNT ON -- 停止在部份結果集中傳回顯示 Transact-SQL 陳述式或預存程序所影響之資料列數的訊息
INSERT tempdb.dbo.tbGO1 VALUES(SYSDATETIME());
INSERT tempdb.dbo.tbGO2 VALUES(NEWID());
GO 100

--03 若是加上分號,會有錯誤
INSERT tempdb.dbo.tbGO1 VALUES(SYSDATETIME());
INSERT tempdb.dbo.tbGO2 VALUES(NEWID());
GO 2;

/*
錯誤訊息:

發生嚴重的指令碼錯誤。
剖析 GO 時發現不正確的語法。
*/

--04 查詢資料表:tbGO1、tbGO2
SELECT * FROM tempdb.dbo.tbGO1;
SELECT * FROM tempdb.dbo.tbGO2;
GO

--05 刪除範例資料表::tbGO1、tbGO2
USE tempdb
GO
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[tbGO1]') AND type in (N'U'))
DROP TABLE [dbo].[tbGO1]
GO
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[tbGO2]') AND type in (N'U'))
DROP TABLE [dbo].[tbGO2]
GO

-- 01_在 GO 之前的批次將會執行 2 次數



-- 02_在 GO 之前的批次將會執行 1000 次



-- 03_若是加上分號,會有錯誤



-- 04_查詢資料表的結果





認識 GO (Transact-SQL)

GO 不是 Transact-SQL 陳述式;它是 sqlcmd 和 osql 公用程式與 SQL Server Management Studio 程式碼編輯器都能夠辨識的命令。

SQL Server 公用程式會將 GO 解譯成應該將目前的 Transact-SQL 陳述式批次傳送給 SQL Server 執行個體的信號。

目前的陳述式批次由在上一個 GO 之後輸入的所有陳述式組成;如果是第一個 GO,便是從特定工作階段或指令碼開始之後輸入的所有陳述式組成。

Transact-SQL 陳述式不能和 GO 命令佔用同一行。
不過,這一行可包含註解。

使用者必須遵照批次的規則。
例如,在批次內第一個陳述式之後,執行預存程序都必須包括 EXECUTE 關鍵字。

本機 (使用者自訂) 變數的範圍只限於批次,在 GO 命令之後,便不能參考它。

SQL Server 應用程式可以將多個 Transact-SQL 陳述式傳給 SQL Server 執行個體,以利用批次方式來執行它們。

之後,會將批次中的這些陳述式編譯成單一執行計畫。

在 SQL Server 公用程式內執行特定陳述式的程式設計人員,或建立要在 SQL Server 公用程式中執行的 Transact-SQL 陳述式指令碼之程式設計人員,都利用 GO 來作為批次結束的信號。

如果以 ODBC 或 OLE DB API 為基礎的應用程式試圖執行 GO 命令,就會收到語法錯誤。

SQL Server 公用程式永遠不會將 GO 命令傳給伺服器。



認識批次

批次是指從應用程式同時傳送到 SQL Server 執行的一或多個 Transact-SQL 陳述式群組。

SQL Server 將批次的陳述式編譯成單一可執行單元,稱為執行計畫。然後一次執行完畢該執行計畫中的陳述式。

Transact-SQL 陳述式應該使用分號終止。

這不是強制性的需求,但是會取代不使用分號結束陳述式的功能,而且在未來版本的 Microsoft SQL Server 中可能會移除這個功能。

編譯錯誤 (例如語法錯誤) 會妨礙執行計畫的編譯。因此,不會執行批次中的任何陳述式。

--

執行階段錯誤 (像是算術溢位或條件約束違規) 會有下列其中一種影響:

1. 大部分的執行階段錯誤會停止目前的陳述式和批次中隨後進行的陳述式。
2. 某些執行階段錯誤 (像是強制違規) 只會停止目前的陳述式。批次中所有剩餘的陳述式都會執行。

在發生執行階段錯誤的陳述式之前執行的陳述式不受影響。
唯一的例外是如果批次在交易中,而該錯誤造成交易回復。

在這種情況下,執行階段錯誤回復之前所做的任何未認可的資料修改都會回復。

例如,假設某個批次中有 10 個陳述式。如果第五個陳述式有語法錯誤,批次中的所有陳述式都不會執行。

如果此批次已經完成編譯,但在執行第二個陳述式時失敗,因為第一個陳述式已經執行,所以其結果不受影響。

SQL Server 提供陳述式層級重新編譯。

也就是說,如果陳述式觸發重新編譯,則只有該陳述式會重新編譯,而非整個批次。此行為與 SQL Server 2000 不同。



參考資料:

Executing a TSQL batch multiple times using GO
http://www.mssqltips.com/sqlservertip/1216/executing-a-tsql-batch-multiple-times-using-go/

GO (Transact-SQL)
http://technet.microsoft.com/zh-tw/library/ms188037.aspx

GO -- SQL Server 2000 版本
http://msdn.microsoft.com/en-us/library/aa258908(v=SQL.80).aspx

批次
http://technet.microsoft.com/zh-tw/library/ms175502.aspx

沒有留言:

張貼留言