';' в начале операторов 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:

Обратите внимание, что я спрашиваю о ';' в начале заявлений. Этот вопрос не дублирует этот

Когда следует использовать точки с запятой в SQL Server?

Обновление 2:

Ответ на

@MartinSmith имеет смысл.

Чтобы убедиться, что у нас есть полный ответ на этот пост, рассмотрите эту уважаемую статью:

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

В этот момент вы можете сказать себе: он, должно быть, тянет мой ноги, действительно ли Microsoft называет команду; THROW? Разве это не просто БРОСИТЬ? Правда, если вы посмотрите его в Books Online, точка с запятой. Но точка с запятой должна быть там. Официально это терминатор для предыдущего оператора, но он не является обязательным и от каждого используют точки с запятой, чтобы прекратить выполнение своих T-SQL-инструкций.

Я согласен с ответом @MartinSmith, но кажется, что дело доходит до некоторых довольно экстремальных уровней.

Как правило, в хранимой процедуре THROW является выражением по собственной строке. Разработчики SQL просто не просто объединяют такие строки SQL и пропускают точку с запятой.

Для меня больше шансов, что люди случайно сбросили таблицу, чем смешение оператора "THROW" с другой строкой TSQL

Объясняется ли в приведенной цитате что-то чрезвычайное и редкое? или я здесь не хватает места?

Ответ 1

Предполагается, что это должно быть после заявлений, не находящихся перед ними. Но в большинстве случаев в TSQL конечные полуколоны на операторах в настоящее время являются необязательными на практике (хотя технически Не заканчивая операторы Transact-SQL с точкой с запятой устаревший), а наличие заявления, заканчивающего полуколоны, не применяется.

Исключением является оператор MERGE (для которого требуется завершающий полуплот), а также выражения, предшествующие WITH или THROW

Итак, это несколько защитная практика для ответов на 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;  

Неправильный синтаксис около ';'.

Я установил пример, который вы указали в своем вопросе, и изменил его на

; 

--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;

Итак, чтобы упростить работу, когда CTE был введен в SQL Server 2005, и когда в SQL Server 2012 был добавлен бросок, требуется, чтобы предыдущий оператор был завершен терминатором оператора.

Та же причина, по которой требуется требование ; в конце оператора слияния.

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);

Легче разобрать код и посмотреть, где заканчивается утверждение.