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

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

那么什么时候用呢?

202875 次浏览

从一个SQLServerCentral.Com 文章由Ken Powers:

分号

分号字符是语句结束符。它是ANSI SQL-92标准的一部分,但从未在Transact-SQL中使用过。事实上,编写T-SQL代码好几年都不会遇到分号。

使用

有两种情况必须使用分号。第一种情况是使用公共表表达式(CTE),而CTE不是批处理中的第一个语句。第二种情况是您发出一个servicebroker语句,而servicebroker语句不是批处理中的第一个语句。

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

如果你只发送一条语句,技术上来说你可以不用语句结束符;在脚本中,当您发送多个语句时,就需要它。

在实践中,即使只向数据库发送一条语句,也应始终包含结束符。

编辑:对于那些说语句终止符不是[特定的RDBMS]所要求的,虽然这可能是真的,但它们是ANSI SQL标准所要求的。在所有的编程中,如果我们能够在不损失功能的情况下坚持一个标准,我们就应该这样做,因为这样我们的代码或习惯就不会受制于一个专有的供应商。

对于一些C编译器,main可以返回void,尽管标准要求main返回int。但是这样做会使我们的代码和我们自身的可移植性降低。

有效编程的最大困难不是学习新东西,而是忘记坏习惯。从某种程度上说,我们可以避免养成坏习惯,这对我们、对我们的代码,以及任何阅读或使用我们代码的人来说都是一种胜利。

个人意见:只在需要的地方使用它们。(请参阅TheTXI的回答,以获得所需的列表。)

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

[此意见是针对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

在SQL2008 BOL中,他们说在下一个版本中将需要分号。因此,要经常使用它。

参考:

分号似乎不应该与游标操作一起使用:OPENFETCHCLOSEDEALLOCATE。我在这上面浪费了几个小时。我仔细查看了BOL,并注意到[;]没有显示在这些游标语句的语法中!!

所以我有:

OPEN mycursor;

这给了我错误16916。

但是:

OPEN mycursor

工作。

当在包含其他语句的批处理中使用DISABLE或ENABLE TRIGGER语句时,它前面的语句必须以分号结束。否则,您将得到一个语法错误。我用这个把头发都扯掉了……后来,我偶然发现了这个MS Connect项目。它关闭了,无法修复。

看到在这里

如果我读得正确,将要求使用分号来结束TSQL语句。 http://msdn.microsoft.com/en-us/library/ms143729%28v=sql.120%29.aspx < / p > < p >编辑: 我找到了SSMS 2008R2的一个插件,它将格式化脚本并添加分号。我认为它仍处于测试阶段

http://www.tsqltidy.com/tsqltidySSMSAddin.aspx < a href = " http://www.tsqltidy.com/tsqltidySSMSAddin.aspx " > < / >

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

分号在复合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)

必须使用它。

使用分号来终止语句的做法是标准的,实际上是一种要求 在其他几个数据库平台上。SQL Server只要求在特定情况下使用分号 case—但是在不需要分号的情况下,使用分号不会引起问题。 我强烈建议您采用用分号结束所有语句的做法。 这样做不仅可以提高代码的可读性,而且在某些情况下确实可以 给你省点麻烦。(当需要一个分号并且没有指定时,错误消息SQL . SQL 服务器产生的不总是很清楚。)

最重要的是:

SQL Server文档指出不能用 分号是不赞成使用的特性。这意味着长期目标是强制使用 该产品的未来版本中的分号。这又多了一个进入 终止所有语句的习惯,即使目前不需要

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


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

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

enter image description here

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

enter image description here

我仍然有很多关于T-SQL的知识要学习,但在为事务编写一些代码(并基于来自stackoverflow和其他站点的示例代码)时,我发现了一个情况,其中似乎需要分号,如果缺少分号,语句似乎根本不执行,也没有引发错误。以上的答案似乎都没有涉及到这一点。(本文使用的是MS SQL Server 2012。)

一旦我让事务以我想要的方式工作,我决定在它周围放一个try-catch,这样如果有任何错误,它就会回滚。只有在这样做之后,事务才没有提交(SSMS在试图关闭窗口时确认这一点,并发出一条漂亮的消息,提醒您有一个未提交的事务。

所以这

COMMIT TRANSACTION

在BEGIN TRY/END TRY块外可以很好地提交事务,但在块内必须如此

COMMIT TRANSACTION;

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

幸运的是,这导致了一个巨大的问题,立即就可以明显地看出有问题。不幸的是,由于没有报告错误(语法或其他),所以问题并不明显。

相反,ROLLBACK TRANSACTION在BEGIN CATCH块中使用分号或不使用分号似乎都同样有效。

这可能有一定的逻辑,但它给人的感觉是武断的,像爱丽丝梦游仙境一样。

注意:这回答了书面的问题,但不是陈述的问题。把它添加到这里,因为人们会搜索它

在递归CTE语句中,分号也用于WITH之前:

;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]组成。它是通过创建一个值为1的表来完成的,然后递归直到达到10。

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

Transact-SQL语句结束符。虽然在这个版本的SQL Server中,分号在大多数语句中都不是必需的,但在未来的版本中,分号将是必需的。

(另见@gerryLowry的评论)

如果你想在SQLServer中得到随机的命令超时错误,那么在CommandText字符串的末尾去掉分号。

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

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

又名-> 在实践中,即使只向数据库发送一条语句,也应始终包含结束符。