控制流語句
批處理:
一個批處理段是由一個或者多個語句組成的一個批處理,之所以叫批處理是因為所有語句一次性被提交到一個SQL實例。
- 批處理是分批提交到SQL Server示例,因此在不同的批處理里局部變量不可訪問。
- 在不同批處理中,流程控制語句不能跨批處理。
- 如果想讓多個語句分多次提交到SQL實例,則需要使用GO關鍵字。GO關鍵字本身並不是一個SQL語句,GO關鍵字可以看作是一個批處理結束的標識符,當遇到GO關鍵字時,當前GO之前的語句會作為一個批處理直接傳到SQL實例執行。
不同的批處理局部變量不可訪問,例如:
DECLARE @i int; SET @i = 1; GO --分批了 PRINT @i --@i在這個批里未定義
輸出:
消息 137,級別 15,狀態 2,第 1 行
必須聲明標量變量 "@i"。
控制流語句不能跨批處理,例如:
DECLARE @i int; SET @i = 1; IF(@i = 1) PRINT('1'); GO --分批了 ELSE PRINT('不知道'); --ELSE找不到IF了,控制流語句不跨批,因此報錯。
輸出結果如下:
1 消息 156,級別 15,狀態 1,第 1 行 關鍵字 'ELSE' 附近有語法錯誤。
控制流語句也稱為流程控制語句,是和高級編程語言中的類似功能一致的,引入控制流語句將使T-SQL代碼有順序執行轉變為按控制執行。
1、程序塊語句BEGIN...END
程序塊語句用於將多條T-SQL語句封裝起來構成一個程序塊。SQLServer在處理時,將整個程序塊視為一條T-SQL語句執行。
begin <T-SQL命令行或程序塊> end
經常與while或if...else組合起來使用,可以相互嵌套。
2、判斷語句IF...ELSE
if...else語句用於條件測試,系統將根據條件滿足與否來決定如何執行語句,else子句是可選的。
語法:
if 邏輯表達式 語句塊1 else 語句塊2 語句塊3
if的形式通常包括if exists(用於判斷是否存在)和if not(是否條件不滿足)
綜合示例:
DECLARE @i int SET @i = 10; IF(@i < 5) PRINT '小於5'; ELSE IF(@i < 8) BEGIN PRINT '小於8' END ELSE BEGIN PRINT '前面都不滿足!' END
以上代碼在SQL Server中執行后輸出前面都不滿足!
3、循環語句WHILE
while語句用於執行循環,可以根據循環條件重復執行語句塊。通常使用break和continue關鍵字在循環內部進行控制。
語法:
while<條件表達式> <sql語句塊1> [break] <sql語句塊2> [continue] <sql語句塊3>
break語句讓程序跳出循環體,結束while的循環。
continue語句讓程序跳過[sql語句塊3],回到while<條件表達式>,重新判斷邏輯值執行。
where語句可以互相嵌套。
示例:
DECLARE @i int; SET @i = 0; WHILE(@i < 10) BEGIN SET @i = @i + 1; IF(@i % 2 = 0) BEGIN PRINT('跳過2的倍數' + CAST(@i AS varchar)); CONTINUE; END ELSE IF (@i = 7) BEGIN PRINT('到' + CAST(@i AS varchar) + '就跳出循環'); BREAK; END PRINT @i; END
輸出結果如下所示:
1 跳過2的倍數2 3 跳過2的倍數4 5 跳過2的倍數6 到7就跳出循環
4、分支判斷語句CASE
CASE語句用於執行多條件的分支判斷。
語法格式:
CASE input_expression WHEN when_expression THEN result_expression [...n] [ ELSE else_result_expression ] END
現在來寫個實例:先給出一張表:
要求查出以下信息:
SQL語句如下:
select Team,Rq, sum(case when winlose='勝' then 1 else 0 end) as 勝,sum(case when winlose='負' then 1 else 0 end) as 負 from test group by Rq,Team having Team = '曼聯'
再來一個,一張表只有Id,Sex兩個字段,要求用一條SQL語句將Sex字段的'男'變'女','女'變'男'。
update table_1 set sex = (case when sex='男' then '女' when sex='女' then '男' end)
執行完SQL語句后,結果如下:
再來一個有一張表,里面有3個字段:語文,數學,英語。其中有3條記錄分別表示語文70分,數學80分,英語58分,請用一條sql語句查詢出這三條記錄大於或等於80表示優秀,大於或等於60表示及格,小於60分表示不及格。
SQL語句如下:
select Id, (case when chinese >= 80 then '優秀' when chinese >= 60 then '及格' else '不及格' end) as 語文, (case when math >= 80 then '優秀' when math >= 60 then '及格' else '不及格' end) as 數學, (case when english >= 80 then '優秀' when english >= 60 then '及格' else '不及格' end) as 英語 from fenshu
5、無條件退出語句RETURN
RETURN語句用於使程序從一個查詢、存儲過程或批量處理中無條件返回,其后面的語句不再執行。如果在存儲過程中使用return語句,那么此語句可以指定返回給調用應用程序、批處理或過程的整數;如果沒有為return指定整數值,那么該存儲過程將返回0。
存儲過程返回值:
返回值 | 含義 |
0 | 存儲過程執行成功 |
-1 | 沒有找到數據庫對象 |
-2 | 數據類型錯誤 |
-3 | 進程死鎖錯誤 |
-4 | 進程死鎖錯誤 |
-5 | 語法錯誤 |
-6 | 其他用戶錯誤 |
-7 | 資源錯誤 |
-8 | 非致命的內部錯誤 |
-9 | 達到系統配置參數極限 |
-10 | 內部一致性致命錯誤 |
-11 | 內部一致性致命錯誤 |
-12 | 表或索引崩潰 |
-13 | 數據庫崩潰 |
-14 | 硬件錯誤 |
語法:
return [整數表達式]
示例:
BEGIN PRINT(1); PRINT(2); RETURN; PRINT(3); --在RETURN之后的代碼不會被執行,因為會跳過當前批處理 END GO BEGIN PRINT(4); END
輸出如下:
1 2 4
6、無條件跳轉語句GOTO
GOTO語句可以使程序無條件跳轉到指定的程序執行點,增加了程序設計的靈活性。但破壞了程序的結構化,使程序結構變得復雜而且難以測試。
語法:
GOTO 語句標識符
使用說明:
語句標識符可以是數字或者字母的組合,但必須以":"結束。而在GOTO語句后的標識符不必帶":"。
注意事項:
GOTO語句和跳轉標簽可以在存儲過程、批處理或語句塊中的任何地方使用,但不能超出批處理的范圍。
示例:
DECLARE @i int; SET @i = 1; SET @i = 2; SET @i = 3; SET @i = 4; GOTO ME; SET @i = 5; --這行被跳過了 SET @i = 6; --這行被跳過了 SET @i = 7; --這行被跳過了 ME:PRINT('跳到我了?'); PRINT @i
輸出結果如下:
跳到我了? 4
7、延期執行語句WAITFOR
waitfor語句用於掛起語句的執行,直到指定的時間點或者指定的時間間隔。
1、指定時間點的語法
waitfor { Time 'time' }
示例:
WAITFOR DELAY '00:00:03' BEGIN PRINT '延遲3秒輸出!'; END
2、指定等待時間間隔的語法
waitfor { delay 'interval' }
interval為時間間隔,指定執行waitfor語句之前需要等待的時間,最多為24小時。
waitfor語句常用語某個特定的時間點或時間間隔自動執行某些任務。在waitfor語句中不能包含打開游標,定義視圖這樣的操作。在包含事務的語句中不要使用waitfor語句,因為waitfor語句在時間點或時間間隔執行期間將一直擁有對象的鎖,當事務中包含waitfor語句,事務的其他語句又需要訪問被鎖住的數據對象事就容易發生死鎖現象。
示例:對着始終來看真是分毫不差啊。
WAITFOR TIME '15:49:22' BEGIN PRINT '定時輸出' END