语句块是程序中一个相对独立的执行单元,它是由关键字BEGIN…END括起来而造成的代码段。其中,BEGIN用于标识语句块的开始,END则标识语句块的结束。语句块能够嵌套定义。
语句块一般与IF、WHILE等控制语句一块儿使用,以界定这些控制语句的做用范围。这在下面介绍控制语句的部分会涉及到。sql
SQL Server支持两种形式的IF语句:IF…和IF…ELSE…句型。数据库
该句型的语法格式以下: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
有时候在做出判断之后,对不知足条件表达式的状况也要进行相应的处理,这时能够选用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
当须要做两次或两次以上的判断并根据判断结果做出执行选择时,通常要使用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
IF语句通常用于一个判断有少许出口(特别是两个出口)的状况。但在许多时候可能遇到一个判断有不少出口的状况,这时若是仍然使用IF语句,可能使得语句在结构上变得很是复杂。但若是换用CASE语句,将使得语句代码变得很精炼、简洁。 在SQL Server中,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 张宇,山地自行车
如下是搜索式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函数定义计算列,能够大大较少前台代码的编写工做量。
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
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
相似于其余高级语言,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;
RETURN语句用于从过程、批处理或语句块中无条件退出,RETURN以后的语句不被执行。其语法以下:
RETURN [integer_expression]
RETURN能够后跟整型表达式,当执行到RETURN语句的时候先计算该表达式的值,而后返回该值。
若是将RETURN语句嵌入存储过程,该语句不能返回空值。
若是某个过程试图返回空值,则将生成警告消息并返回0值。
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;