不管哪一種語言都具備流程控制的功能,用來控制程式執行與流程的流向,透過流程控制可以讓程式更容易維護。
這次要討論很多結構化語言不建議使用的指令: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 批次的次數啊!
倒是還沒使用過 GOTO 的指令
感謝分享
GOTO 最大的問題就是破壞程式的結構,控制不好就會變成脫韁野馬
但是卻是一種很直覺的寫法