流程控制語(yǔ)句

順序語(yǔ)句

①set語(yǔ)句
??set語(yǔ)句有兩種用法瞬矩,除了用于給局部變量賦值姑廉,還可以設(shè)定用戶執(zhí)行T-SQL命令時(shí)SQL Server的處理選項(xiàng)饭望,一般有以下幾種設(shè)定方式讨阻。

  • set 選項(xiàng) on:選項(xiàng)開(kāi)關(guān)打開(kāi)芥永。
  • set 選項(xiàng) off:選項(xiàng)開(kāi)關(guān)關(guān)閉。
  • set 選項(xiàng)值:設(shè)定選項(xiàng)的具體值

例如钝吮,設(shè)置顯示/隱藏受T-SQL語(yǔ)句影響的行數(shù)消息語(yǔ)句埋涧,其語(yǔ)法如下:

set nocount(on|off)

②select輸出語(yǔ)句和print輸出語(yǔ)句
??SQL Server使用print或select輸出信息。
??select作為輸出使用時(shí)的語(yǔ)法如下:

select 表達(dá)式1[,表達(dá)式2,...,表達(dá)式n]

print用于向屏幕輸出信息奇瘦,其語(yǔ)法如下:

print 表達(dá)式
  • select輸出會(huì)包含分隔線
  • print輸出類型一定要是字符類型

【示例】

1> print 'Hello World!'
2> go
Hello World!
1> select 'Hello World!'
2> go

------------
Hello World!

分支語(yǔ)句

①IF...ELSE語(yǔ)句

IF Boolean_expression   
     { sql_statement | statement_block }
[ELSE   
     { sql_statement | statement_block } ]   

說(shuō)明:

  • IF...ELSE語(yǔ)句間不只包含一條語(yǔ)句時(shí)棘催,必須使用BEGIN...END包含多條語(yǔ)句的語(yǔ)句塊。
  • 語(yǔ)句塊的關(guān)鍵字BEGIN耳标、END必須成對(duì)出現(xiàn)醇坝,允許嵌套,并且BEGIN...END之間至少包含一條SQL語(yǔ)句。
  • IF...ELSE可以嵌套使用

【示例】

DECLARE @Number int;  
SET @Number = 50;  
IF @Number > 100  
   PRINT 'The number is large.';  
ELSE   
   BEGIN  
      IF @Number < 10  
      PRINT 'The number is small.';  
   ELSE  
      PRINT 'The number is medium.';  
   END ;  
GO  

②CASE函數(shù)
??CASE是計(jì)算條件列表呼猪,并返回多個(gè)可能的結(jié)果表達(dá)式之一画畅。
??CASE 表達(dá)式有兩種格式:

  • CASE 簡(jiǎn)單表達(dá)式,它通過(guò)將表達(dá)式與一組簡(jiǎn)單的表達(dá)式進(jìn)行比較來(lái)確定結(jié)果宋距。
  • CASE 搜索表達(dá)式轴踱,它通過(guò)計(jì)算一組布爾表達(dá)式來(lái)確定結(jié)果。

這兩種格式都支持可選的 ELSE 參數(shù)谚赎。
??CASE 可用于允許使用有效表達(dá)式的任意語(yǔ)句或子句淫僻。 例如,可以在 SELECT壶唤、UPDATE雳灵、DELETE 和 SET 等語(yǔ)句以及 select_list、IN闸盔、WHERE悯辙、ORDER BY 和 HAVING 等子句中使用 CASE。
??CASE語(yǔ)法:

--簡(jiǎn)單Case函數(shù)
CASE input_expression   
     WHEN when_expression THEN result_expression [ ...n ]   
     [ ELSE else_result_expression ]   
END   
--Case搜索函數(shù)
CASE  
     WHEN Boolean_expression THEN result_expression [ ...n ]   
     [ ELSE else_result_expression ]   
END  

【返回類型】從的類型集中返回優(yōu)先級(jí)高的類型result_expressions和可選else_result_expression迎吵。

CASE 表達(dá)式不能用于控制 Transact-SQL 語(yǔ)句笑撞、語(yǔ)句塊、用戶定義函數(shù)以及存儲(chǔ)過(guò)程的執(zhí)行流钓觉。能控制的只有IF..ELSE、WHILE這樣的控制流語(yǔ)言坚踩。

【示例】
A. 使用帶有 CASE 簡(jiǎn)單表達(dá)式的 SELECT 語(yǔ)句

SELECT   ProductNumber, Category =  
      CASE ProductLine  
         WHEN 'R' THEN 'Road'  
         WHEN 'M' THEN 'Mountain'  
         WHEN 'T' THEN 'Touring'  
         WHEN 'S' THEN 'Other sale items'  
         ELSE 'Not for sale'  
      END,  
   Name  
FROM Production.Product  
ORDER BY ProductNumber;  
GO  

B. 使用帶有 CASE 搜索表達(dá)式的 SELECT 語(yǔ)句
在 SELECT 語(yǔ)句中荡灾,CASE 搜索表達(dá)式允許根據(jù)比較值替換結(jié)果集中的值。 下面的示例根據(jù)產(chǎn)品的價(jià)格范圍將標(biāo)價(jià)顯示為文本注釋瞬铸。

SELECT   ProductNumber, Name, "Price Range" =   
      CASE   
         WHEN ListPrice =  0 THEN 'Mfg item - not for resale'  
         WHEN ListPrice < 50 THEN 'Under $50'  
         WHEN ListPrice >= 50 and ListPrice < 250 THEN 'Under $250'  
         WHEN ListPrice >= 250 and ListPrice < 1000 THEN 'Under $1000'  
         ELSE 'Over $1000'  
      END  
FROM Production.Product  
ORDER BY ProductNumber ;  
GO  

C. 在 ORDER BY 子句中使用 CASE
下面的示例在 ORDER BY 子句中使用 CASE 表達(dá)式批幌,以根據(jù)給定的列值確定行的排序順序。

SELECT BusinessEntityID, SalariedFlag  
FROM HumanResources.Employee  
ORDER BY CASE SalariedFlag WHEN 1 THEN BusinessEntityID END DESC  
        ,CASE WHEN SalariedFlag = 0 THEN BusinessEntityID END;  
GO  

D. 在 SET 語(yǔ)句中使用 CASE

SET @ContactType =   
        CASE   
            -- Check for employee  
            WHEN EXISTS(SELECT * FROM HumanResources.Employee AS e   
                WHERE e.BusinessEntityID = @BusinessEntityID)   
                THEN 'Employee'  
  
            -- Check for vendor  
            WHEN EXISTS(SELECT * FROM Person.BusinessEntityContact AS bec  
                WHERE bec.BusinessEntityID = @BusinessEntityID)   
                THEN 'Vendor'  
  
            -- Check for store  
            WHEN EXISTS(SELECT * FROM Purchasing.Vendor AS v            
                WHERE v.BusinessEntityID = @BusinessEntityID)   
                THEN 'Store Contact'  
  
            -- Check for individual consumer  
            WHEN EXISTS(SELECT * FROM Sales.Customer AS c   
                WHERE c.PersonID = @BusinessEntityID)   
                THEN 'Consumer'  
        END;  

循環(huán)語(yǔ)句

T-SQL中的循環(huán)語(yǔ)句只有while一種語(yǔ)法形式嗓节,while語(yǔ)句還可以和break荧缘、continue語(yǔ)句一起使用。其結(jié)構(gòu)如下所示:

WHILE Boolean_expression   
     { sql_statement | statement_block | BREAK | CONTINUE }  
  • WHILE語(yǔ)句可以嵌套
  • WHILE語(yǔ)句間不只包含一條語(yǔ)句時(shí)拦宣,必須使用BEGIN...END包含多條語(yǔ)句的語(yǔ)句塊截粗。
  • CONTINUE:使 WHILE 循環(huán)重新開(kāi)始執(zhí)行,忽略 CONTINUE 關(guān)鍵字后面的任何語(yǔ)句鸵隧。
  • BREAK:導(dǎo)致從最內(nèi)層的 WHILE 循環(huán)中退出绸罗。 執(zhí)行標(biāo)記的末尾循環(huán)中,在結(jié)束關(guān)鍵字后顯示的任何語(yǔ)句豆瘫。
  • 如果嵌套了兩個(gè)或多個(gè) WHILE 循環(huán)珊蟀,則內(nèi)層的 BREAK 將退出到下一個(gè)外層循環(huán)。 將首先運(yùn)行內(nèi)層循環(huán)結(jié)束之后的所有語(yǔ)句外驱,然后重新開(kāi)始下一個(gè)外層循環(huán)育灸。

【示例】

USE AdventureWorks2012;  
GO  
WHILE (SELECT AVG(ListPrice) FROM Production.Product) < $300  
BEGIN  
   UPDATE Production.Product SET ListPrice = ListPrice * 2  
   SELECT MAX(ListPrice) FROM Production.Product  
   IF (SELECT MAX(ListPrice) FROM Production.Product) > $500  
      BREAK  
   ELSE  
      CONTINUE  
END  
PRINT 'Too much for the market to bear';  

其他控制語(yǔ)句

①WAITFOR語(yǔ)句
??waitfor語(yǔ)句稱為延時(shí)語(yǔ)句腻窒,它的功能暫停程序執(zhí)行,直到所設(shè)定的等待時(shí)間已過(guò)或所設(shè)定的時(shí)間已到才繼續(xù)玩下執(zhí)行磅崭。儿子。其語(yǔ)法如下:

WAITFOR   
{  
    DELAY 'time_to_pass'   
  | TIME 'time_to_execute'   
  | [ ( receive_statement ) | ( get_conversation_group_statement ) ]   
    [ , TIMEOUT timeout ]  
}  
  • DELAY:用來(lái)設(shè)定等待時(shí)間,最多可達(dá)24小時(shí)绽诚。
  • time_to_pass:等待的時(shí)段典徊。 time_to_pass可接受格式之一指定datetime數(shù)據(jù),也可以指定為本地變量恩够。
  • TIME:指定的運(yùn)行批處理卒落、存儲(chǔ)過(guò)程或事務(wù)的時(shí)間。
  • time_to_execute:WAITFOR 語(yǔ)句完成的時(shí)間蜂桶。 time_to_execute可接受格式之一指定datetime數(shù)據(jù)儡毕,也可以指定為本地變量。

【示例】
A. 使用 WAITFOR TIME
下面的示例在晚上 10:20 在 msdb 數(shù)據(jù)庫(kù)中執(zhí)行 sp_update_job 存儲(chǔ)過(guò)程扑媚。

EXECUTE sp_add_job @job_name = 'TestJob';  
BEGIN  
    WAITFOR TIME '22:20';  
    EXECUTE sp_update_job @job_name = 'TestJob',  
        @new_name = 'UpdatedJob';  
END;  
GO  

B. 使用 WAITFOR DELAY
以下示例在兩小時(shí)的延遲后執(zhí)行存儲(chǔ)過(guò)程腰湾。

BEGIN  
    WAITFOR DELAY '02:00';  
    EXECUTE sp_helpdb;  
END;  
GO  

C. 在 WAITFOR DELAY 中使用局部變量
以下示例顯示如何對(duì) WAITFOR DELAY 選項(xiàng)使用局部變量。 將創(chuàng)建一個(gè)存儲(chǔ)過(guò)程疆股,該過(guò)程將等待可變的時(shí)間段费坊,然后將經(jīng)過(guò)的小時(shí)、分鐘和秒數(shù)信息返回給用戶旬痹。

CREATE PROCEDURE dbo.TimeDelay_hh_mm_ss   
(@DelayLength char(8)= '00:00:00')  
AS  
DECLARE @ReturnInfo varchar(255)  
IF ISDATE('2000-01-01 ' + @DelayLength + '.000') = 0  
    BEGIN  
        SELECT @ReturnInfo = 'Invalid time ' + @DelayLength   
        + ',hh:mm:ss, submitted.';
        PRINT @ReturnInfo   
        RETURN(1)  
    END  
BEGIN  
    WAITFOR DELAY @DelayLength  
    SELECT @ReturnInfo = 'A total time of ' + @DelayLength + ',   
        hh:mm:ss, has elapsed! Your time is up.'  
    PRINT @ReturnInfo;  
END;  
GO  
EXEC TimeDelay_hh_mm_ss '00:00:10';  
GO  

②RETURN語(yǔ)句
??從查詢或過(guò)程中無(wú)條件退出附井。 RETURN 的執(zhí)行是即時(shí)且完全的,可在任何時(shí)候用于從過(guò)程两残、批處理或語(yǔ)句塊中退出永毅。 RETURN 之后的語(yǔ)句是不執(zhí)行的。其語(yǔ)法如下:

RETURN [<整形表達(dá)式>]

錯(cuò)誤處理語(yǔ)句

a. 簡(jiǎn)單的異常處理
??在T-SQL程序中人弓,把可能出現(xiàn)異常的程序語(yǔ)句放置在try部分(begin try...end tey)沼死,錯(cuò)誤處理語(yǔ)句放置在catch部分(begin catch...end catch),如果在try部分未發(fā)生錯(cuò)誤崔赌,則catch部分的語(yǔ)句會(huì)被忽略意蛀,如果try部分的語(yǔ)句發(fā)生了異常,則程序控制轉(zhuǎn)移至相應(yīng)的catch部分峰鄙。如果try..catch捕獲了錯(cuò)誤并進(jìn)行了處理浸间,對(duì)于調(diào)用者來(lái)說(shuō),相當(dāng)于沒(méi)發(fā)生錯(cuò)誤吟榴。
??如下面語(yǔ)句在try部分不會(huì)發(fā)生錯(cuò)誤魁蒜,catch部分的語(yǔ)句也不會(huì)被執(zhí)行:

begin try
  print 10/2;
  print 'No error';
end try
begin catch
  print 'Error!Divided by zero.'
end catch

b. 預(yù)定義異常
??在一般T-SQL程序設(shè)計(jì)中,編程者應(yīng)該在catch部分分析錯(cuò)誤原因,然后給出相應(yīng)提示信息或其他處理語(yǔ)句兜看。
??catch部分捕獲到的錯(cuò)誤以錯(cuò)誤號(hào)來(lái)標(biāo)識(shí)锥咸,編程者通過(guò)調(diào)用error-numer()函數(shù)得到捕獲到的錯(cuò)誤號(hào),然后根據(jù)錯(cuò)誤號(hào)給出相關(guān)錯(cuò)誤提示信息细移,或者調(diào)用error-message()函數(shù)顯示系統(tǒng)預(yù)先定義的錯(cuò)誤信息搏予,SQL Server的所有預(yù)定以錯(cuò)誤號(hào)及對(duì)應(yīng)錯(cuò)誤信息可以通過(guò)查詢sys.message得到。另外弧轧,SQL Server不支持用戶自定義異常雪侥。
??下面示例說(shuō)明try...catch的用法。創(chuàng)建表t精绎,用于測(cè)試:

1> create table t
2> (
3>   a int not null,
4>   b int not null,
5>   c char(4),
6>   constraint pk_t primary key(a),
7>   constraint ck_b check(b>100)
8> )

然后執(zhí)行下面程序段:

begin try
  insert into t values(1,170,'a');
end try
begin catch
  if error_number() = 2627
  begin 
    print 'Handling PK violation...';
  end

  else if error_number() = 547
  begin 
    print 'Handling CHECK/FK constraint violation...';
  end

  else if error_number() = 515
  begin 
    print 'Handling NULL violation...';
  end

  else if error_number() = 245
  begin 
    print 'Handling conversion error...';
  end

  else
  begin 
    print 'Handling unknow error...';
  end

-- 輸出錯(cuò)誤號(hào)
print 'Error Number:'+cast(error_number() as varchar(10));
-- 輸出錯(cuò)誤信息
print 'Error Message:'+error_message();
print 'Error Severity:'+cast(error_severity() as varchar(10));
print 'Error State:'+cast(error_state() as varchar(10));
print 'Error Line:'+cast(error_line() as varchar(10));
print 'Error Proc:'+coalesce(error_procedure(),'Not within proc');

end catch

如果第二次執(zhí)行上面的語(yǔ)句速缨,則會(huì)因?yàn)橹麈I存在重復(fù)值而給出以下錯(cuò)誤信息:

Handling PK violation...
Error Number:2627
Error Message:違反了 PRIMARY KEY 約束 'pk_t'。不能在對(duì)象 'dbo.t' 中插入重復(fù)鍵代乃。
Error Severity:14
Error State:1
Error Line:2
Error Proc:Not within proc

如果把添加記錄的insert語(yǔ)句改為:
??insert into t values(2,10,'a');
??修改后旬牲,重新執(zhí)行上述程序段,則違反了b字段上的check約束搁吓,會(huì)給出以下錯(cuò)誤信息:

Handling CHECK/FK constraint violation...
Error Number:547
Error Message:INSERT 語(yǔ)句與 CHECK 約束"ck_b"沖突原茅。該沖突發(fā)生于數(shù)據(jù)庫(kù)"master", 表"dbo.t", column 'b'堕仔。
Error Severity:16
Error State:0
Error Line:2
Error Proc:Not within proc

c. 使用存儲(chǔ)過(guò)程處理異常
??如果要使得錯(cuò)誤處理的代碼可以重用擂橘,則可以把上述catch的內(nèi)容創(chuàng)建為存儲(chǔ)過(guò)程,以后即可在T-SQL代碼中直接調(diào)用摩骨。
??創(chuàng)建存儲(chǔ)過(guò)程如下:

create procedure dbo.err_message
as
 if error_number() = 2627
  begin 
    print 'Handling PK violation...';
  end

  else if error_number() = 547
  begin 
    print 'Handling CHECK/FK constraint violation...';
  end

  else if error_number() = 515
  begin 
    print 'Handling NULL violation...';
  end

  else if error_number() = 245
  begin 
    print 'Handling conversion error...';
  end

  else
  begin 
    print 'Handling unknow error...';
  end

-- 輸出錯(cuò)誤號(hào)
print 'Error Number:'+cast(error_number() as varchar(10));
-- 輸出錯(cuò)誤信息
print 'Error Message:'+error_message();
print 'Error Severity:'+cast(error_severity() as varchar(10));
print 'Error State:'+cast(error_state() as varchar(10));
print 'Error Line:'+cast(error_line() as varchar(10));
print 'Error Proc:'+coalesce(error_procedure(),'Not within proc');

在T-SQL程序段中調(diào)用上述存儲(chǔ)過(guò)程:

begin try
  insert into t values(2,10,'a');
end try
begin catch
  exec err_message;
end catch
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末贝室,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子仿吞,更是在濱河造成了極大的恐慌,老刑警劉巖捡偏,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件唤冈,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡银伟,警方通過(guò)查閱死者的電腦和手機(jī)你虹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)彤避,“玉大人傅物,你說(shuō)我怎么就攤上這事×鹪ぃ” “怎么了董饰?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我卒暂,道長(zhǎng)啄栓,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任也祠,我火速辦了婚禮昙楚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘诈嘿。我一直安慰自己堪旧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布奖亚。 她就那樣靜靜地躺著淳梦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪遂蛀。 梳的紋絲不亂的頭發(fā)上谭跨,一...
    開(kāi)封第一講書(shū)人閱讀 49,842評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音李滴,去河邊找鬼螃宙。 笑死,一個(gè)胖子當(dāng)著我的面吹牛所坯,可吹牛的內(nèi)容都是我干的谆扎。 我是一名探鬼主播,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼芹助,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼堂湖!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起状土,我...
    開(kāi)封第一講書(shū)人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤无蜂,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后蒙谓,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體斥季,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年累驮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了酣倾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谤专,死狀恐怖躁锡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情置侍,我是刑警寧澤映之,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布拦焚,位于F島的核電站,受9級(jí)特大地震影響惕医,放射性物質(zhì)發(fā)生泄漏耕漱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一抬伺、第九天 我趴在偏房一處隱蔽的房頂上張望螟够。 院中可真熱鬧,春花似錦峡钓、人聲如沸妓笙。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)寞宫。三九已至,卻和暖如春拉鹃,著一層夾襖步出監(jiān)牢的瞬間辈赋,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工膏燕, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钥屈,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓坝辫,卻偏偏與公主長(zhǎng)得像篷就,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子近忙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容