首页 文章

';'在TSQL语句的开头

提问于
浏览
10

我不时会看到以分号“;”开头的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语句的开头

Update 1:

请注意,我在询问';'在陈述的开头 . 这个问题与此问题不重复

When should I use semicolons in SQL Server?

Update 2:

@MartinSmith的回答很有意义 .

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

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

此时你可能会对自己说:他必须拉我的腿,微软真的称之为命令;那么?不仅仅是THROW吗?没错,如果您在联机丛书中查找,则没有领先的分号 . 但分号必须在那里 . 正式地说,它是前一个语句的终结符,但它是可选的,并且远非每个人都使用分号来终止它们的T-SQL语句 .

我同意@MartinSmith的答案,但似乎这个问题正处于一些非常极端的程度 .

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

对我来说,人们不可避免地放弃一张 table ,而不是将“THROW”语句与另一行TSQL混合

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

2 回答

  • 13

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

    一个例外是 MERGE 语句(确实需要一个终止的半冒号)以及 WITHTHROW 之前的语句

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

    关键字'with'附近的语法不正确 . 如果此语句是公用表表达式,xmlnamespaces子句或更改跟踪上下文子句,则必须以分号结束前一个语句 .

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

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

    CREATE VIEW V1
    AS
      WITH T(X)
           AS (SELECT 1)
      SELECT *
      FROM   T;
    

    同样地, THROW 盲目地插入一个前导的半结肠也会引起问题 .

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

    ';'附近的语法不正确 .

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

    ; 
    
    --Ensure that any immediately preceding statement is terminated with a semicolon above
    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;
    
  • 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);
    

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

相关问题