2016-08-07 4 views
10

Время от времени я вижу утверждения SQL Server, которые начинаются с точки с запятой ';' как показано ниже';' в начале инструкций TSQL

;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

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

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

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

Для меня, есть больше шансов, люди случайно удалить таблицу, чем смешение заявления разбрасывались 'с другой линией TSQL

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

ответ

13

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

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

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

Неверный синтаксис рядом с ключевым словом 'with'. Если этот оператор является общим выражением таблицы , предложением контекста xmlnames или предложением контекста изменения , предыдущий оператор должен быть прерван точкой с запятой .

В случае, если предыдущее заявление является завершается точкой с запятой дополнительный один не делает никакого вреда. Он просто рассматривается как пустой оператор.

Эта практика сама по себе может вызывать проблемы, хотя 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; 
+0

Благодарим вас за помощь. Можете ли вы поделиться своим, хотя и по моим обновленным комментариям? –

+0

@AllanXu - Да, я согласен с вашими настроениями на '; THROW' - Эта практика - это только то, что я хотел бы рассмотреть для образцов кода в Интернете. Не что-то в моем собственном исходном коде. Как правильная вещь - просто убедиться, что вы завершаете предыдущие утверждения (и в идеале все заявления) с полуколонами. –

2

Это думает, что это о предоставлении анализатора воюя шанс, чтобы выяснить, что код должен делать.

не является зарезервированным ключевым словом, а 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 и когда бросок был добавлен в 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); 

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

Смежные вопросы