185.流程設計

1.語句塊

  語句塊是程序中一個相對獨立的執行單元,它是由關鍵字BEGIN…END括起來而造成的代碼段。其中,BEGIN用於標識語句塊的開始,END則標識語句塊的結束。語句塊能夠嵌套定義。
  語句塊一般與IF、WHILE等控制語句一塊兒使用,以界定這些控制語句的做用範圍。這在下面介紹控制語句的部分會涉及到。sql

 

 

 

2 IF語句

   SQL Server支持兩種形式的IF語句:IF…和IF…ELSE…句型。數據庫

 

 

2.1 IF…句型

 

該句型的語法格式以下:express

IF expression
     { sql_statement | statement_block } 

 


     expression爲布爾表達式,若是該表達式中含有 SELECT 語句,必須用圓括號將 SELECT 語句括起來;sql_statement表示SQL語句;statement_block表示語句塊(下同)。若是expression的返回值爲TRUE,則執行IF後面的語句或語句塊,不然什麼都不執行。

IF語句的結構流程圖如圖6.2所示。函數

 



【例6.6】 查詢學號爲「20170202」的學生,若是該學生成績及格則將其姓名和成績打印出來。
該查詢要求可用局部變量和IF…句型來實現:post

USE MyDatabase
GO
DECLARE @no char(8), @name char(8), @avgrade numeric(3,1)
SET @no = '20170202'
SELECT @name = s_name, @avgrade = s_avgrade
FROM student
WHERE s_no = @no;
IF @avgrade>60.0
BEGIN
PRINT @name
PRINT @avgrade
END
GO

 


2.2 IF…ELSE…句型


  有時候在做出判斷之後,對不知足條件表達式的狀況也要進行相應的處理,這時能夠選用IF…ELSE…句型。其語法格式以下:spa

IF expression
     { sql_statement1 | statement_block1 }
ELSE
     { sql_statement2 | statement_block2} 

 


  該語句的結構流程圖如圖6.3所示。
3d

 



【例6.7】 對於給定學號的查詢,若是平均成績不及格的則打印姓名和平均成績,不然打印學號便可。實現代碼以下:code

USE MyDatabase
GO
DECLARE @no char(8), @name char(8), @avgrade numeric(3,1)
SET @no = '20170202'
SELECT @name = s_name, @avgrade = s_avgrade
FROM student
WHERE s_no = @no;
IF @avgrade<60.0
BEGIN
     PRINT @name
     PRINT @avgrade
END
ELSE
     PRINT @no
GO

 


2.3 IF … ELSE IF … ELSE …句型


   當須要做兩次或兩次以上的判斷並根據判斷結果做出執行選擇時,通常要使用IF … ELSE IF … ELSE …句型。該句型的語法格式以下:blog

IF expression1
     { sql_statement1 | statement_block1 }
ELSE IF expression2
     {sql_statement2 | statement_block2}
[ELSE IF expression3
     {sql_statement3 | statement_block3}
…]
ELSE
     {sql_statementn | statement_blockn} 

 




上述語句的結構流程圖如圖6.4所示。開發

 

 

 

 



【例6.8】 運用多分支的IF句型來查詢並實現分等級打印學生成績。

USE MyDatabase
GO
DECLARE @no char(8), @name char(8), @avgrade numeric(3,1)
SET @no = '20170202'
SELECT @name = s_name, @avgrade = s_avgrade
FROM student
WHERE s_no = @no;
IF @avgrade>=90.0
  PRINT '優秀'
ELSE IF @avgrade>=80.0
  PRINT '良好'
ELSE IF @avgrade>=70.0
  PRINT '中等'
ELSE IF @avgrade>=60.0
  PRINT '及格'
ELSE
  PRINT '不及格'
GO

 


3 CASE語句

 


  IF語句通常用於一個判斷有少許出口(特別是兩個出口)的狀況。但在許多時候可能遇到一個判斷有不少出口的狀況,這時若是仍然使用IF語句,可能使得語句在結構上變得很是複雜。但若是換用CASE語句,將使得語句代碼變得很精煉、簡潔。  在SQL Server中,CASE語句其實是被看成一個函數來執行,執行後都有一個返回值。它有兩種類型,一種是簡單式,一種是搜索式。

 

 

3.1簡單式CASE函數  

 

如下是簡單式CASE函數的語法格式:

CASE input_expression
WHEN when_expression THEN result_expression
  [ ...n ]
[
  ELSE else_result_expression
]
END 

 


  執行時,首先計算表達式input_expression的值,而後將計算結果與WHEN子句中的表達式進行比較,若是相等則計算THEN後面的表達式result_expression,並將獲得的值做爲整個CASE函數的值,同時退出CASE函數;若是結果與全部WHEN子句中的表達式的值都不相等,則計算ELSE後面的表達式else_result_expression。無論最後是計算哪一個表達式,它的結果都將做爲整個CASE函數的返回值。
  when_expression 是任意有效的表達式。但input_expression 及每一個WHEN 子句中的表達式when_expression的數據類型必須相同或是可隱式轉換的數據類型。

【例6.9】 首先使用SELECT語句查詢學生的學號,而後用CASE函數對學生的姓名和愛好進行簡要說明。
實現代碼以下:

SELECT 學號 = s_no, 姓名及愛好 =  
   CASE s_no
WHEN '20170201' THEN '劉洋,游泳'
WHEN '20170202' THEN '王曉珂,爬山'
WHEN '20170203' THEN '王偉志,滑雪'
WHEN '20170204' THEN '嶽志強,支部書記'
WHEN '20170205' THEN '賈簿,足球'
WHEN '20170206' THEN '李思思,愛好不詳'
WHEN '20170207' THEN '蒙恬,長跑'
WHEN '20170208' THEN '張宇,山地自行車'
ELSE '沒有這我的‘
  END
FROM student

 

該語句執行後結果以下:
學號        姓名及愛好
--------------------------------------------
20170201    劉洋,游泳
20170202    王曉珂,爬山
20170203    王偉志,滑雪
20170204    嶽志強,支部書記
20170205    賈簿,足球
20170206    李思思,愛好不詳
20170207    蒙恬,長跑
20170208    張宇,山地自行車

 

 

 

3.2搜索式CASE函數

 


  如下是搜索式CASE函數的語法格式:

CASE
WHEN expression THEN result_expression
  [ ...n ]
[
  ELSE else_result_expression
]
END

 


        在搜索式CASE函數中,關鍵字CASE後面沒有表達式,且WHEN後面的表達式expression已被限定爲布爾表達式(返回值爲TRUE或FALSE)。執行時,依次從上到下計算每一個WHEN子句中表達式expression的值,若是值爲TRUE則計算該WHEN子句中表達式result_expression的值,並將該值返回做爲CASE函數的值;若是全部WHEN子句中表達式expression的值均爲FALSE,則計算ELSE後面表達式else_result_expression的值並將其返回做爲CASE函數的值。

【例6.10】 使用搜索式CASE函數來顯示學生的成績等級。
相應代碼以下:

SELECT 學號 = s_no, 姓名 = s_name, 成績等級 =
CASE
WHEN s_avgrade>90.0 THEN '優秀'
WHEN s_avgrade>80.0 THEN '良好'
WHEN s_avgrade>70.0 THEN '中等'
WHEN s_avgrade>60.0 THEN '及格'
ELSE '不及格'
END
FROM student

 


該語句執行後結果以下:

學號        姓名        成績等級
-------------------------------------------------
20170201    劉洋        優秀
20170202    王曉珂      良好
20170203    王偉志      良好
20170204    嶽志強      中等
20170205    賈簿        不及格
20170206    李思思      及格
20170207    蒙恬        中等
20170208    張宇        不及格



   【例6.11】 爲保證指導學生的質量,如今不少高校都從工做量上限制教師指導學生的人數。假設某高校制定以下的指導工做量公式,其中n爲指導的學生人數:
                                                   指導工做量 =
請從新建立結構如表5.9所示的數據表(見例5.2),要求用上述公式從新定義表示工做量的字段c_hour,其餘字段不變。
     根據上述要求,爲表supervisor 從新編寫CREATE TABLE語句代碼,結果以下:

CREATE TABLE supervisor(
t_no    int            PRIMARY KEY,
t_name  varchar(8)     NOT NULL,
s_n     int            NOT NULL     CHECK(s_n>=0 and s_n<=20),
c_hour  AS             
    CASE
         WHEN s_n<=8 THEN 15* s_n
         WHEN s_n<=10 THEN 15*8+12*(s_n-8)
         ELSE 15*8+12*2+5
         END
);

 




  用上述CREATE TABLE語句從新建立數據表supervisor,而後用下列INSERT語句添加數據:

insert supervisor values('19970101','方瓊',7)
insert supervisor values('19970102','趙構',9)
insert supervisor values('19970103','李方正',15)    

 


    
結果表supervisor中的數據以下:
t_no    t_name    s_n               c_hour
---------------------------------------------------------------
19970101    方瓊     7    105
19970102    趙構     9    132
19970103    李方正    15    149

      能夠看到,只要正確設置字段s_n的值,工做量字段c_hour的值會自動計算產生。在軟件開發中,若是可以靈活地利用CASE函數定義計算列,能夠大大較少前臺代碼的編寫工做量。


4 WHILE語句

WHILE語句是典型的循環控制語句,其語法格式以下:

WHILE expression
     {sql_statement | statement_block}  

 

 
  在WHILE語句中,只要表達式expression的值爲真,就重複執行循環體中的語句。若是布爾表達式中含有SELECT語句,則必須用括號將SELECT語句括起來。
   WHILE語句也能夠結合BREAK和CONTINUE語句一塊兒使用,它們能夠嵌入循環體內部,用於控制WHILE循環中語句的執行。
  其中,當執行到BREAK語句時,程序將無條件退出當前的循環體,執行出如今END關鍵字(循環體結束的標記)後面的語句;
  當執行到CONTINUE語句時,程序將不執行CONTINUE關鍵字後面的全部語句,提早結束本次循環(但沒有退出循環體,這是與BREAK語句的不一樣之處),並從新開始新的一輪循環。


WHILE語句的結構流程圖如圖6.5所示。

 



【例6.12】 若是學生成績的平均值低於95分則循環執行對每一個學生的成績增長0.5%。在循環過程當中,若是發現最高成績超過99分則退出循環;在加分過程當中,當成績的平均值大於或等於75.5分時打印出當前成績的平均值。

USE MyDatabase;
GO
DECLARE @max numeric(3,1),@avg numeric(3,1);
SET @avg = (SELECT AVG(s_avgrade) FROM student)
SET @max = (SELECT MAX(s_avgrade) FROM student)
WHILE @avg < 95
BEGIN
   IF @max > 99 BREAK          --退出循環體
   UPDATE student SET s_avgrade = s_avgrade + s_avgrade * 0.005
   SET @avg = (SELECT AVG(s_avgrade) FROM student)
   SET @max = (SELECT MAX(s_avgrade) FROM student)   
   IF @avg < 75.5 CONTINUE        --結束本次循環
   PRINT '當前平均成績:'+STR(@avg, 5, 1);  
END

 


5 GOTO語句


  GOTO語句是一種無條件轉移語句,能夠實現程序的執行流程從一個地方轉移到另外的任意一個地方。與IF語句結合,GOTO語句也能夠實現WHILE語句的循環功能。可是使用GOTO語句會下降程序的可讀性,因此在通常狀況下不提倡在程序中使用GOTO語句。
     使用GOTO語句時,首先要定義標籤,而後才能使用GOTO語句。其語法格式以下:

Label:
{sql_statement | statement_block}
[IF …] GOTO Label;

 


  其中,Label爲定義的標籤,它是GOTO語句轉向的依據。
  標籤必須符合標識符命名規則。不管是否使用 GOTO 語句,標籤都可做爲註釋方法使用。
  當執行到語句「GOTO Label」時,執行流程將無條件轉到標籤Label所指向的地址,並從該地址起依次往下執行所遇到的語句。


  【例6.13】 使用了GOTO語句來實現1到100的累加,結果放在局部變量@sum中,最後將結果打印出來。

DECLARE @s int, @sum int
SET @s = 0
SET @sum = 0
label1:
SET @s = @s + 1
SET @sum = @sum + @s
IF @s <> 100 GOTO label1
PRINT @sum

 


6 TRY…CATCH語句

 


  相似於其餘高級語言,Transact-SQL也有異常的捕獲和處理語句——TRY…CATCH語句。該語句的語法格式以下:

BEGIN TRY
     { sql_statement | statement_block }
END TRY
BEGIN CATCH
     { sql_statement | statement_block }
END CATCH[ ; ]

 


  當TRY塊內的語句產生錯誤時,則會將控制傳遞給CATCH塊的第一個語句;當TRY塊所包含的代碼中沒有錯誤時,則在TRY塊中最後一個語句完成後將控制傳遞給緊跟在END CATCH 語句以後的語句。


 【例子】下例中第二條插入語句有錯誤,因此在執行到該語句時程序將轉到CATCH塊中執行打印語句。這時第一條插入語句已經成功執行,而第三條插入語句則未能執行到,因此只有第一條數據被插入,而其餘數據沒有被插入到數據庫中。

USE MyDatabase;
GO
DELETE FROM student
GO
BEGIN TRY
INSERT student VALUES('20170201','劉洋','','1997-02-03','計算機應用技術',98.5,'計算機系');
    -- 下面語句中,時間常量'1997-09-201'格式錯誤
INSERT student VALUES('20170202','王曉珂','','1997-09-201','計算機軟件與理論',88.1,'計算機系');
INSERT student VALUES('20170203','王偉志','','1996-12-12','智能科學與技術',89.8,'智能技術系');
END TRY
BEGIN CATCH
  PRINT N'插入操做有錯誤。'
END CATCH;

 


7 RETURN語句

 


  RETURN語句用於從過程、批處理或語句塊中無條件退出,RETURN以後的語句不被執行。其語法以下:

RETURN [integer_expression] 

 


  RETURN能夠後跟整型表達式,當執行到RETURN語句的時候先計算該表達式的值,而後返回該值。
  若是將RETURN語句嵌入存儲過程,該語句不能返回空值。
  若是某個過程試圖返回空值,則將生成警告消息並返回0值。

 

 

8 WAITFOR語句


  WAITFOR語句用於設置指定程序段的執行時間,包括指定程序段在某一時刻執行或者在某一段時間間隔以後自動執行。其語法格式以下:

WAITFOR
{
  DELAY 'time_to_pass'
  | TIME 'time_to_execute'   
}

 


  DELAY子句用於設定WAITFOR語句所要等待的時間(這個時間事後即執行WAITFOR後面的語句),時間的長短由參數time_to_pass說明(但只能包含時間部分,不能包含日期部分),最長爲24小時;TIME子句用於設定WAITFOR語句等待的終結時刻,由參數time_to_execute說明,可使用datetime數據類型接受的格式,但也只能包含時間部分。


【例6.14】 設置在下午5:30(17:30)執行學生成績查詢。

USE MyDatabase;
GO
WAITFOR TIME '17:30';
SELECT 姓名 = s_name, 平均成績 = s_avgrade
FROM student

 

若是要求上述查詢在1小時20分鐘後執行,則可使用下面的代碼實現:

USE MyDatabase;
GO
WAITFOR DELAY '01:20';
SELECT 姓名 = s_name, 平均成績 = s_avgrade
FROM student;

 




 

 

 

相關文章
相關標籤/搜索