';'在TSQL语句的开头

时间:2016-08-07 17:42:49

标签: sql-server tsql

我不时会看到以分号';'开头的SQL Server语句如下所示

;WITH cte
     AS (SELECT ROW_NUMBER() OVER (PARTITION BY Col1, Col2, Col3 
                                       ORDER BY ( SELECT 0)) RN
         FROM   #MyTable)
DELETE FROM cte
WHERE  RN > 1

另一个例子是;THROW

为什么确实存在';' TSQL语句的开头

更新1:

请注意我问的是';'在陈述的开头。这个问题与这个问题不重复

When should I use semicolons in SQL Server?

更新2:

@MartinSmith回答很有意义。

为了确保我们对这篇文章有完整的答案,请考虑这篇受人尊敬的文章:

http://www.sommarskog.se/error_handling/Part1.html#jumpTHROW

  

此时你可能会对自己说:他必须拉我的   微软真的称之为命令; THROW?不是吗   扔?没错,如果你在联机丛书中查找,就没有领先优势   分号。但分号必须在那里。官方说来,它是一个   前一个语句的终止符,但它是可选的,而且远   来自每个人都使用分号来终止他们的T-SQL语句。

我同意@MartinSmith的答案,但似乎这件事情正处于一些非常极端的程度。

通常,在存储过程中,THROW是由其自己的行声明。 SQL开发人员不仅仅是合并这样的SQL行而且会错过分号。

对我而言,人们意外丢弃表格的可能性要大于将“THROW”语句与另一行TSQL混合的可能性

上面的引文中是否解释了一些极端且罕见的事情?或者我在这里错过了一点?

2 个答案:

答案 0 :(得分:13)

应该是在他们之前的陈述之后。但在TSQL的大多数情况下,语句中的终止半冒号在实践中目前是可选的(尽管技术上Not ending Transact-SQL statements with a semicolon已被弃用)并且不强制存在终止半冒号的语句。

异常是=IF(B2="","",IF(ISNUMBER(MATCH(B2,keywords!$B$2:$B$5,0)),"Fruit",IF(ISNUMBER(MATCH(B2,keywords!$C$2:$C$5,0)),"Nature",IF(ISNUMBER(MATCH(B2,keywords!$D$2:$D$5,0)),"Vehicle","no match"))))语句(确实需要终止分号)以及MERGEWITH之前的语句

因此,对于StackOverflow上的答案,如果OP(或未来的读者)将其粘贴到某个现有批次的中间,并且在前面的语句中没有所需的半冒号,然后抱怨,这是一个有点防御性的做法它没有工作,他们收到以下错误。

  

关键字'附近有'的语法不正确。如果这个陈述是   公用表表达式,xmlnamespaces子句或更改跟踪   context子句,前一个语句必须以a结尾   分号。

如果前面的语句 以分号结尾,则额外的语句不会造成伤害。它只是被视为一个空洞的陈述。

虽然在多语句无效的上下文中使用CTE,但这种做法本身可能会导致问题。例如在THROW之前插入分号会破坏分号。

WITH

同样地,对于CREATE VIEW V1 AS WITH T(X) AS (SELECT 1) SELECT * FROM T; ,盲目地插入一个前导的半结肠也会导致问题。

THROW
  

&#39 ;;'

附近的语法不正确

我修复了the example you give in your question并将其更改为

IF @i IS NULL
;THROW 50000, '@i IS NULL', 1;  

答案 1 :(得分:2)

它认为这是为了让解析器有机会弄清楚代码应该做什么。

throw不是保留关键字,with可以用作其他语句的一部分。

Transact-SQL中完全有效的语句:

create table throw
(
  ID int
) 
with(data_compression = none) 

请注意,换行符不是解析器用于将一个语句与另一个语句分开的东西。

create 
table 
throw(ID int) 
with (data_compression = none) insert into 
throw values(1) select 
* from throw

它使用其他一些魔法来弄清楚你真的是这个意思。

create table throw(ID int) 
with (data_compression = none);

insert into throw values(1);

select * 
from throw;

因此,为了在SQL Server 2005中引入CTE时更容易,并且在SQL Server 2012中添加了throw,则需要使用语句终止符终止前面的语句。

在合并声明结束时要求;的相同原因。

declare @T table(ID int, Value int);

merge into @T as T
using (values(1, 100)) as S(ID, Value)
on T.ID = S.ID
when matched then 
  update set Value = S.Value
when not matched then
  insert (ID, Value) values(S.ID, S.Value);

更容易解析代码并查看语句实际结束的位置。