';' в начале операторов 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);
Легче разобрать код и посмотреть, где заканчивается утверждение.