什么时候应该在SQL Server中使用分号?

在检查Web上的一些代码和SQL Server Management Studio生成的脚本时,我注意到一些语句以分号结尾。

那我应该什么时候使用它?

从Ken Powers的SQLServerCentral.Com 文章 :

分号

分号字符是一个语句结束符。 它是ANSI SQL-92标准的一部分,但从未在Transact-SQL中使用过。 事实上,有可能对T-SQL进行编码多年,而不会遇到分号。

用法

有两种情况必须使用分号。 第一种情况是使用公用表expression式(CTE)的地方,而CTE不是批处理中的第一条语句。 第二个是您发布Service Broker语句的位置,而Service Broker语句不是批处理中的第一条语句。

默认情况下,SQL语句以分号结尾。 除非你(很less)设置了新的语句结束符,否则你可以使用分号来终止语句。

如果你只发送一个声明,在技术上可以省去声明终止符; 在一个脚本中,当你发送多个语句时,你需要它。

实际上,即使只是向数据库发送一条语句,也应该包含终止符。

编辑:为了回应那些声明语句结束符不是[特定的RDBMS]所要求的,虽然这可能是正确的,但它们是ANSI SQL标准所要求的。 在所有的编程中,如果我们能够坚持一个标准而不会失去function,那么我们就应该这样做,因为那样我们的代码和习惯都不和一个专有供应商联系在一起。

使用一些C编译器,即使标准要求main返回int,也可能有主返回void。 但是这样做会使我们的代码和我们自己的可移植性降低。

有效编程最大的困难是不学习新事物,这是不好的习惯。 就我们可以避免习惯坏习惯而言,这对我们,我们的代码,以及任何阅读或使用我们的代码的人来说都是一个胜利。

在SQL2008 BOL中,他们说在下一个版本中需要分号。 所以,一定要使用它。

参考:

  • Transact-SQL语法约定(Transact-SQL)
  • SQL Server 2008 R2中不推荐使用的数据库引擎function (“未来版本的SQL Server中不支持的function”部分,“Transact-SQL”区域)

如果我正确地阅读了这一点,那么使用分号来结束TSQL语句将是一个要求。 http://msdn.microsoft.com/en-us/library/ms143729%28v=sql.120%29.aspx

编辑:我find了SSMS 2008R2插件,将格式化您的脚本并添加分号。 我认为它仍处于testing阶段

http://www.tsqltidy.com/tsqltidySSMSAddin.aspx

编辑:我发现了一个更好的免费工具/插件名为ApexSQL … http://www.apexsql.com/

个人意见:只在需要的地方使用。 (请参阅TXI上面的答案以获取所需的列表。)

由于编译器不需要它们,所以你可以把它们放在一边,但为什么呢? 编译器不会告诉你你忘记了哪一个,所以最终会导致不一致的使用。

[这个意见是特定于SQL Server的。 其他数据库可能有更严格的要求。 如果您正在编写SQL以在多个数据库上运行,则您的要求可能会有所不同。]

上面提到的tpdi,“在一个脚本中,当你发送一个以上的声明时,你需要它。 这其实是不正确的。 你不需要他们。

 PRINT 'Semicolons are optional' PRINT 'Semicolons are optional' PRINT 'Semicolons are optional'; PRINT 'Semicolons are optional'; 

输出:

 Semicolons are optional Semicolons are optional Semicolons are optional Semicolons are optional 

必须使用它。

使用分号来终止语句的做法是标准的,实际上是其他数据库平台的一个要求。 SQL Server仅在特定情况下才需要分号 – 但在不需要分号的情况下,使用分号不会导致问题。 我强烈build议你采用用分号终止所有语句的做法。 这样做不仅可以提高代码的可读性,还可以在某些情况下为您节省一些痛苦。 (当需要分号并且没有指定分号时,SQL Server产生的错误信息并不总是很清楚。)

最重要的是:

SQL Server文档指出不终止带有分号的T-SQL语句是不推荐使用的function。 这意味着长期目标是在未来版本的产品中强制使用分号。 这就是为什么要养成终止你的所有陈述的习惯的一个原因,即使在目前没有要求的情况下也是如此。

资料来源:Itzik Ben-Gan的Microsoft SQL Server 2012 T-SQL基础知识


一个为什么你总是必须使用的例子; 是以下两个查询(从这个post复制):

 BEGIN TRY BEGIN TRAN SELECT 1/0 AS CauseAnException COMMIT END TRY BEGIN CATCH SELECT ERROR_MESSAGE() THROW END CATCH 

在这里输入图像说明

 BEGIN TRY BEGIN TRAN SELECT 1/0 AS CauseAnException; COMMIT END TRY BEGIN CATCH SELECT ERROR_MESSAGE(); THROW END CATCH 

在这里输入图像说明

我仍然有很多东西要学习T-SQL,但是在为事务处理一些代码(并且基于来自stackoverflow和其他站点的示例的代码)时,我发现了一个似乎需要分号的情况,如果它丢失了,该声明似乎并没有执行,也没有提出任何错误。 这似乎没有涵盖在任何上述的答案。 (这是使用MS SQL Server 2012)。

一旦我按照我想要的方式进行事务处理,我决定尝试一下,如果有任何错误,就会回滚。 只有在这样做之后,事务才会被提交(SSMS在试图closures窗口时确认了这一点,并提供了一个很好的消息,提醒您事实上有一个未提交的事务。

所以这

 COMMIT TRANSACTION 

在BEGIN TRY / END TRY块之外,工作正常,但是在块内必须进行

 COMMIT TRANSACTION; 

请注意,没有提供错误或警告,也没有提示事务在尝试closures查询选项卡之前仍未提交。

幸运的是,这会造成如此大的问题,以至于显而易见的是存在一个问题。 不幸的是,由于没有报告任何错误(语法或其他),所以并不明显是什么问题。

相反,ROLLBACK TRANSACTION似乎在BEGIN CATCH块中有效或无分号地工作。

这可能有一些逻辑,但它感到任意,爱丽丝梦游仙境。

根据Transact-SQL语法约定(Transact-SQL) (MSDN)

Transact-SQL语句终止符。 尽pipe此版本的SQL Server中大多数语句不需要使用分号,但将来的版本中将需要该分号。

(另见@gerryLowry的评论)

看起来,分号不应与光标操作一起使用:OPEN,FETCH,CLOSE和DEALLOCATE。 我只是浪费了几个小时。 我仔细看了一下BOL,注意到这些游标语句的语法没有显示[;]!

所以我有:OPEN mycursor; 这给了我错误16916。

但是:开放mycursor工作。

我无法回复@rab出于某种原因,所以我不得不发表一个答案:

我不知道SQL Server使用的是哪个版本的SQL,但是分号可以在SQL Server 2005和2008的游标中正常工作。

尝试以下,看看我的意思是:

 DECLARE @tblSource TABLE ( CharCol VARCHAR(20) ); INSERT INTO @tblSource (CharCol) VALUES ('First'); INSERT INTO @tblSource (CharCol) VALUES ('Second'); DECLARE @text VARCHAR(20); DECLARE csr CURSOR LOCAL FAST_FORWARD FOR SELECT CharCol FROM @tblSource ORDER BY CharCol; OPEN csr; FETCH NEXT FROM csr INTO @text; WHILE @@FETCH_STATUS = 0 BEGIN; PRINT @text; FETCH NEXT FROM csr INTO @text; END; CLOSE csr; DEALLOCATE csr; 

在包含其他语句的批处理中使用DISABLE或ENABLE TRIGGER语句时,语句必须以分号结尾。 否则,你会得到一个语法错误。 我用这个把我的头发拉出来…然后,我偶然发现了这个MS Connect的东西。 这是封闭的,因为不会修复。

看到这里

分号并不总是在复合SELECT语句中工作。

比较这两个不同版本的琐碎复合SELECT语句。

代码

 DECLARE @Test varchar(35); SELECT @Test= (SELECT (SELECT (SELECT 'Semicolons do not always work fine.';););); SELECT @Test Test; 

回报

 Msg 102, Level 15, State 1, Line 5 Incorrect syntax near ';'. 

但是,代码

 DECLARE @Test varchar(35) SELECT @Test= (SELECT (SELECT (SELECT 'Semicolons do not always work fine.'))) SELECT @Test Test 

回报

 Test ----------------------------------- Semicolons do not always work fine. (1 row(s) affected) 

注意:这个回答问题是书面的,但不是所述的问题。 在这里添加它,因为人们会search它

在recursionCTE语句中使用分号之前也使用分号:

 ;WITH Numbers AS ( SELECT n = 1 UNION ALL SELECT n + 1 FROM Numbers WHERE n+1 <= 10 ) SELECT n FROM Numbers 

这个查询将生成一个名为Numbers的CTE,它由整数[1..10]组成。 这是通过创build一个值为1的表,然后recursion直到达到10来完成的。

如果您喜欢在SQLServer中获取随机命令超时错误,请在CommandTextstring的末尾留下分号。

我不知道这是否logging在任何地方,或者如果它是一个错误,但它确实发生,我从苦痛的经历中学到了这一点。

我有使用SQLServer 2008可validation和可重复的例子。

又名 – > 实际上,即使只是发送一条语句到数据库,也总是包含终止符。