4.6 批处理语句
批处理是从应用程序发送到SQL Server并得以执行的一条或多条T-SQL语句。使用批处理时,有下面一些注意事项。
• 一个批处理中只要存在一处语法错误,整个批处理都无法通过编译。
• 批处理中可以包含多个存储过程,但除第一个过程外,其他存储过程前面都必须使用EXECUTE关键字。
• 某些特殊的SQL指令不能和别的SQL语句共存在一个批处理中,如CREATE TABLE和CREATE VIEW语句。这些语句只能独自存在于一个单独的存储过程中。
• 所有的批处理使用GO作为结束的标志,当编译器读到GO的时候就把GO前面的所有语句当成一个批处理,然后打包成一个数据包发给服务器。
• GO本身不是T-SQL的组成部分,只是一个用于表示批处理结束的前端指令。
• 不能在删除一个对象之后,在同一批处理。
• CREATE DEFAULT、CREATE FUNCTION、CREATE PROCEDURE、CREATE RULE、CREATE SCHEMA、CREATE TRIGGER和CREATE VIEW语句不能在批处理中与其他语句组合使用。批处理必须以CREATE语句开头,所有跟在该批处理后的其他语句将被解释为第一个CREATE语句定义的一部分。
• 如果EXECUTE语句是批处理中的第一句,则不需要EXECUTE关键字。如果EXECUTE语句不是批处理中的第一条语句,则需要EXECUTE关键字。
• 不能在定义一个CHECK约束之后,在同一个批处理中使用。
• 不能在修改表的一个字段之后,立即在同一个批处理中引用这个字段。
• 使用SET语句设置的某些选项值不能应用于同一个批处理中的查询。
在编写批处理程序时,最好能够以分号结束相关的语句。数据库虽然不强制要求,但是笔者还是强烈建议如此处理。一方面是有利于提高批处理程序的可读性。批处理程序往往用来完成一些比较复杂的成套的功能,而每条语句则完成一项独立的功能。此时为了提高其可读性,最好能够利用分号来进行语句与语句之间的分隔。另一方面是与未来版本的兼容性。SQL Server数据库在设计的时候,一开始这方面就把关不严。现在大部分的标准程序编辑器都实现了类似的强制控制。根据现在微软官方提供的资料来看,在以后的SQL Server数据库版本中,这个规则可能会成为一个强制执行的规则,即必须在每条语句后面利用分号来进行分隔。为了能够跟后续的SQL Server数据库版本进行兼容,最好从现在开始就采用分号来分隔批处理程序中的每条语句。
SQL Server提供了语句级重新编译功能。也就是说,如果一条语句触发了重新编译,则只重新编译该语句而不是整个批处理。此行为与SQL Server 2000不同。考虑下面的例子,其中在同一批处理中包含1条CREATE TABLE语句和3条INSERT语句。
CREATE TABLE dbo.t3(a int) ; INSERT INTO dbo.t3 VALUES (1) ; INSERT INTO dbo.t3 VALUES (1,1) ; INSERT INTO dbo.t3 VALUES (3) ; GO SELECT * FROM dbo.t3 ;
在SQL Server中,首先对批处理进行编译。对CREATE TABLE语句进行编译,但由于表dbo.t3尚不存在,因此未编译INSERT语句。然后,批处理开始执行。表已创建。编译第一条INSERT语句,然后立即执行。表现在有一行。然后,编译第二条INSERT语句。编译失败,批处理终止。SELECT语句返回一行。
在SQL Server 2017中,批处理开始执行,同时创建了表。逐一编译3条INSERT语句,但不执行。因为第二条INSERT语句导致一个编译错误,所以整个批处理都将终止。SELECT语句未返回任何行。