为什么CTE应该以分号开头?


14

我只是在看StackOverflow上的一篇文章,其中Aaron Bertrand建议使用CTE代替数字表,这是一种执行手头任务的优雅方法。我的问题是,为什么CTE的第一行以分号开头?

;WITH n AS (SELECT TOP (10000) n FROM 
  (SELECT n = ROW_NUMBER() OVER
    (ORDER BY s1.[object_id])
    FROM sys.all_objects AS s1
    CROSS JOIN sys.all_objects AS s2
  ) AS x ORDER BY n
)
SELECT n FROM n ORDER BY n; -- look ma, no gaps!

这是为了确保WITH语句不会被解析为先前的内容SELECT或其他内容?我在SQL Server 2005 BOL中看不到有关在WITH之前使用分号的任何信息。


Answers:


26

我总是在此处或在StackOverflow上发布时执行此操作,因为对于WITH-由于关键字已超载- 先前的命令要求使用终止分号。如果我粘贴使用CTE的代码示例,则不可避免地会有一些用户将其粘贴到他们现有的代码中,并且前面的语句将没有分号。所以代码中断了,我收到了类似的抱怨:

您的代码坏了!我收到此错误消息:

Incorrect syntax near 'WITH'...

虽然我想相信人们在总是用分号结束他们的陈述方面变得越来越好,但我宁愿先占噪声,而总是将其包括在内。有些人不喜欢它,但是<shrug />。您可以根据需要在有效语句之前或之后包含任意多个分号。这是有效的:

;;;;SELECT 1;;;;;;;;;;;;SELECT 2;;;;;;;;SELECT 3;;;;;

因此,在根据定义需要它的语句之前加一个分号没有什么害处。即使它不是那么漂亮,这样做也是更安全的。

必须用怪异的措词来理解这一点,但是自SQL Server 2008以来,实际上不赞成使用“不使用分号结束有效的语句”。因此,正如我在博客文章中所描述的,即使在它不需要绕过错误,应该在有效的地方使用它。您可以在这里看到:

http://msdn.microsoft.com/en-us/library/ms143729.aspx

(在最后一页搜索“分号”)

如果没有例外,那当然不是SQL Server。尝试这个:

BEGIN TRY;
  SELECT 1/1;
END TRY;
BEGIN CATCH;
  SELECT 1/1;
END CATCH;

这不是该规则的唯一例外,而是我发现最不直观的例外。


1
即使在2012年,我也收到相同的错误消息,但仅由于以下原因是分号END TRYi.stack.imgur.com/rc6dw.png-如果删除该分号,则一切正常。
阿龙贝特朗

我认为您不能将分号放在前面,BEGIN CATCH仅因为它是引入的单个复合语句的一部分BEGIN TRY。这与在IF语句的前面加分号相同ELSE
Andriy M 2012年

@AndriyM我一直在这里进行有关规则的更详细的讨论。我之所以提及它,是因为它令遇到它的每个人感到惊讶,而不是因为我不明白原因。:-)
亚伦·伯特兰

10

这是为了确保它不包含在任何先前的语句中,因为它WITH可以在T-SQL中达到多种目的。

如果这是批次中的第一条语句,我认为您不需要它。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.