Почему CTE должен начинаться с точки с запятой?

14

Я только что посмотрел на пост в StackOverflow, где Аарон Бертран предлагает использовать CTE вместо таблицы чисел, что является элегантным способом выполнения поставленной задачи. Мой вопрос: почему первая строка CTE начинается с точки с запятой?

;WITH n AS (SELECT TOP (10000) n FROM 
  (SELECT n = ROW_NUMBER() OVER
    (ORDER BY s1.[object_id])
    FROM sys.all_objects AS s1
    CROSS JOIN sys.all_objects AS s2
  ) AS x ORDER BY n
)
SELECT n FROM n ORDER BY n; -- look ma, no gaps!

Это для того, чтобы оператор WITH не анализировался в предыдущем SELECTили что-то в этом роде? Я ничего не вижу в SQL Server 2005 BOL об использовании точки с запятой до WITH.

Макс Вернон
источник

Ответы:

26

Я всегда делаю это при публикации здесь или в StackOverflow, потому что для WITH- поскольку ключевое слово перегружено - предыдущая команда требует завершающей точки с запятой. Если я вставлю пример кода, который использует CTE, неизбежно какой-то пользователь вставит его в существующий код, а предыдущий оператор не будет иметь точку с запятой. Таким образом, код нарушается, и я получаю жалобы, как:

Ваш код сломался! Я получил это сообщение об ошибке:

Incorrect syntax near 'WITH'...

Хотя я хотел бы верить, что людям лучше всегда заканчивать свои утверждения точкой с запятой , я бы предпочел предупредить шум и просто всегда включать его. Некоторым людям это не нравится, но <shrug />. Вы можете добавить столько точек с запятой до или после действительного выражения, сколько захотите. Это действительно:

;;;;SELECT 1;;;;;;;;;;;;SELECT 2;;;;;;;;SELECT 3;;;;;

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

Это должно быть сформулировано странно, чтобы понять суть, но «не заканчивая действительный оператор точкой с запятой» фактически не рекомендуется с SQL Server 2008. Поэтому, как я описываю в посте блога, на который я ссылаюсь выше, даже в тех случаях, когда не нужно обходить ошибку, ее следует использовать везде, где допустимо. Вы можете увидеть это здесь:

http://msdn.microsoft.com/en-us/library/ms143729.aspx

(Поиск на последней странице "точка с запятой")

Конечно, это не был бы SQL Server, если бы не было исключений. Попробуй это:

BEGIN TRY;
  SELECT 1/1;
END TRY;
BEGIN CATCH;
  SELECT 1/1;
END CATCH;

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

Аарон Бертран
источник
1
В 2012 году даже я получаю то же сообщение об ошибке, но только из-за точки с запятой после END TRY: i.stack.imgur.com/rc6dw.png - если удалить эту точку с запятой , все работает.
Аарон Бертран
Я думаю, что вы не можете поставить точку с запятой раньше BEGIN CATCHпросто потому, что она является частью одного составного оператора, введенного с BEGIN TRY. Это то же самое, что поставить точку с запятой перед IFоператором ELSE.
Андрей М
@AndriyM Я был знаком с более подробным разговором о правилах здесь. Я упомянул это, потому что это удивление для всех, кто сталкивается с этим, а не потому, что я не понимаю причину. :-)
Аарон Бертран
10

Это сделано для того, чтобы он не был включен ни в какие предыдущие операторы, поскольку WITHв T-SQL может служить различным целям.

Если это первое утверждение в пакете, я не думаю, что оно вам нужно.

swasheck
источник