T-SQL 之 控制流语句
控制流语句也称为流程控制语句,是和高级编程语言中的类似功能一致的,引入控制流语句将使T-SQL代码有顺序执行转变为按控制执行。
批处理:一个批处理段是由一个或者多个语句组成的一个批处理,之所以叫批处理是因为所有语句一次性被提交到一个SQL实例。
[1] 批处理是分批提交到SQL Server示例,因此在不同的批处理里局部变量不可访问。
[2] 在不同批处理中,流程控制语句不能跨批处理。
[3] 如果想让多个语句分多次提交到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' 附近有语法错误。
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(是否条件不满足)
3、循环语句 WHILE
WHILE 语句用于执行循环,可以根据循环条件重复执行语句块。通常使用 BREAK 和 CONTINUE 关键字在循环内部进行控制。语法:
WHILE <条件表达式>
BEGIN <sql语句块1> [break] <sql语句块2> [continue] <sql语句块3>
END
BREAK:程序跳出循环体,结束while的循环。
CONTINUE:程序跳出当前一轮循环,进入下一轮循环。
4、分支判断语句CASE
CASE语句用于执行多条件的分支判断。语法如下:
CASE input_expression WHEN when_expression THEN result_expression [...n] [ ELSE else_result_expression ] END
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 语句标识符
使用说明:
[1] 语句标识符可以是数字或者字母的组合,但必须以":"结束。而在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 语句用于挂起语句的执行,直到指定的时间点或者指定的时间间隔。waitfor语句常用语某个特定的时间点或时间间隔自动执行某些任务。在waitfor语句中不能包含打开游标,定义视图这样的操作。在包含事务的语句中不要使用waitfor语句,因为waitfor语句在时间点或时间间隔执行期间将一直拥有对象的锁,当事务中包含waitfor语句,事务的其他语句又需要访问被锁住的数据对象事就容易发生死锁现象。
[1] 指定时间点的语法
WAITFOR { Time 'time' }
示例:对着时间来看真是分毫不差。
WAITFOR TIME '15:49:22' BEGIN PRINT '定时输出' END
[2] 指定等待时间间隔的语法
WAITFOR { DELAY 'interval' }
interval为时间间隔,指定执行waitfor语句之前需要等待的时间,最多为24小时。
示例:
WAITFOR DELAY '00:00:03' BEGIN PRINT '延迟3秒输出!'; END