iT邦幫忙

DAY 14
11

T-SQL 應用之美系列 第 14

使用流程控制:GOTO

不管哪一種語言都具備流程控制的功能,用來控制程式執行與流程的流向,透過流程控制可以讓程式更容易維護。
這次要討論很多結構化語言不建議使用的指令:GOTO。
先看 GOTO 語法:

-- 定義一個名稱為 label 的標籤
label:
-- 在這裡面寫程式碼
...
...

-- 跳到名稱為 label 的標籤哪邊去執行
GOTO label

-- 定義一個名稱為 execution 的標籤
execution:
-- 在這裡面寫程式碼
...
...

我們可以使用 GOTO 讓程式碼跳到緊接在 GOTO 之後所指定的標籤處繼續執行,而標籤處所在的位置可以在 GOTO 之前或之後。一般來說,會使用 GOTO 的時機,大多是用來離開巢狀迴圈(之所以不使用 BREAK,是因為 BREAK 只能往上跳出一層迴圈)。

GOTO 只能由 WHILE 或 IF...ELSE 的內部往外跳,而不能由外往內跳。另外,GOTO 也只能在同一個批次中,以便跳到其他標籤去,而不能跳到其他不同批次的標籤裡。

把先前在「使用流程控制:WHILE、BREAK 與 CONTINUE」用過的例子:計算從 1 加到 100 的總和,再拿來用,但是這次要改用 GOTO:

-- 定義變數
DECLARE @count int, @sum int

-- 指定初始值
SET @count = 0
SET @sum = 0

-- 開始計算
StartCalculate:
IF (@count < 101)
	BEGIN
		SET @sum = @sum + @count
		SET @count = @count + 1
		GOTO StartCalculate
	END
ELSE
	GOTO StopCalculate

-- 顯示結果
StopCalculate:
SELECT @sum 總和

執行結果:

其實上面的程式碼可以精簡成這樣:

-- 定義變數
DECLARE @count int, @sum int

-- 指定初始值
SET @count = 0
SET @sum = 0

-- 開始計算
StartCalculate:
IF (@count < 101)
	BEGIN
		SET @sum = @sum + @count
		SET @count = @count + 1
		GOTO StartCalculate
	END

-- 顯示結果
SELECT @sum 總和

看出來兩個程式碼的差別沒?第二個程式碼就只是拿掉 ELSE 判斷式跟 StopCalculate 標籤。

剛剛有提到**「批次」**這個字眼,所以接下來,討論跟 GOTO 很像的 GO 指令。熟 T-SQL 指令的人,一定常常要跟 GO 一起 GO!GO!GO!(謝謝 davistai 的「Good job!! Go!Go!Go!」)

其實,GO 不是 T-SQL 的陳述式,它是 sqlcmd 、osql、isql 這幾個公用程式與 SQL Server Management Studio 或 SQL Server Enterprise Manager 程式碼編輯器都能夠辨識的一個命令,以便將目前的 T-SQL 陳述式以**「批次」方式傳送給 SQL Server 進行執行。目前的陳述式批次是由在上一個 GO 之後輸入的所有陳述式組成;如果是第一個 GO,便是從特定工作階段或指令碼開始,於其之後輸入的所有陳述式所組成的,就算是一個「批次」**。

看到下面的程式碼,是否有點眼熟,因為看去跟 GOTO 很像,後面都會接另外一個參數:

PRINT '今天是 ' + CONVERT(char(10), getdate(), 101)
GO 10

難不成 GO 也是可以跳到某個地方去?不是的,看一下 SQL Server 剖析程式碼的畫面:

至於執行的結果畫面則是:

哦!原來 GO 後面所接的那個參數,是指定要執行在 GO 之前的 T-SQL 批次的次數啊!


上一篇
使用流程控制:CASE...WHEN
下一篇
如何在 T-SQL 中宣告變數
系列文
T-SQL 應用之美30

2 則留言

0
鐵殼心
iT邦高手 1 級 ‧ 2008-09-14 01:23:28

結構化語言對 "GOTO" 是深痛惡絕的, 可是他又有它存在的價值.
取捨之間有時候是個兩難.

0
jamesjan
iT邦高手 1 級 ‧ 2008-09-14 06:47:04

倒是還沒使用過 GOTO 的指令
感謝分享

GOTO 最大的問題就是破壞程式的結構,控制不好就會變成脫韁野馬
但是卻是一種很直覺的寫法

我要留言

立即登入留言