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

221

Проверяя некоторый код в Интернете и сценарии, сгенерированные SQL Server Management Studio, я заметил, что некоторые операторы заканчиваются точкой с запятой.

Так, когда я должен использовать это?

Анвар Пинто
источник
23
SQL Server 2008 R2 msdn.microsoft.com/en-us/library/ms177563.aspx "Синтаксические соглашения Transact-SQL (Transact-SQL)" ; == Терминатор Transact-SQL. Хотя точка с запятой не требуется для большинства операторов в этой версии SQL Server, она потребуется в следующей версии .
gerryLowry
2
Хотя они утверждают, что в следующей версии потребуется точка с запятой, это никогда не сбудется. Они никогда не могут поручить это по причинам совместимости. Это сломало бы около 100% приложений.
USR
1
Сейчас 2019 год, и ни одна точка с запятой до сих пор не принята в последней версии SQL Server. Как говорит @usr, если Microsoft не хочет сделать чистый перерыв на 100%, они не смогут обеспечить это.
Ян Кемп

Ответы:

152

Из статьи SQLServerCentral.Com Кена Пауэрса:

Точка с запятой

Точка с запятой является оператором-терминатором. Он является частью стандарта ANSI SQL-92, но никогда не использовался в Transact-SQL. Действительно, можно годами кодировать T-SQL, не встречая точки с запятой.

использование

Есть две ситуации, в которых вы должны использовать точку с запятой. Первая ситуация, когда вы используете общее табличное выражение (CTE), и CTE не является первым оператором в пакете. Во втором случае вы выполняете оператор Service Broker, а оператор Service Broker не является первым оператором в пакете.

TheTXI
источник
9
Является THROWли заявление Service Broker? Мы должны включить точку с запятой перед броском в этом примере:BEGIN ;THROW @Error, 'Invalid FundingID', 2; RETURN END
Крис Уолш
1
Кажется, что они в основном поощряют использование точки с запятой в целом, требуя ее перед всеми новыми типами операторов, которые были введены в последние годы. ( MERGEтоже например). Как упоминалось в других ответах, в стандарте ANSI они обязательны
Марк Соул,
2
@maurocam Я думаю, что вы прочитали документ неправильно. Если вы посмотрите на эту ссылку, она говорит: « Не заканчивайте операторы Transact-SQL точкой с запятой». устарела.
Caltor
На мой взгляд, это не решает вопрос о том, когда нужно (в отличие от необходимости ) использовать точку с запятой.
Стюарт
81

По умолчанию операторы SQL заканчиваются точкой с запятой. Вы используете точку с запятой для завершения операторов, если только вы (редко) не устанавливаете новый терминатор операторов.

Если вы отправляете только один оператор, технически вы можете обойтись без терминатора оператора; в сценарии, когда вы отправляете более одного оператора, он вам нужен.

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

Изменить: в ответ на эти высказывания терминаторы операторов не требуются [конкретной СУБД], хотя это может быть правдой, они требуются стандартом ANSI SQL. Во всем программировании, если мы можем придерживаться Стандарта без потери функциональности, мы должны это делать, потому что тогда ни наш код, ни наши привычки не связаны с одним частным поставщиком.

С некоторыми компиляторами C возможно возвращение main return, даже если стандарт требует main для возврата int. Но это делает наш код и нас самих менее переносимыми.

Самая большая трудность в программировании - не изучение новых вещей, а отучивание от вредных привычек. В той степени, в которой мы можем избежать приобретения вредных привычек, это выигрыш для нас, для нашего кода и для всех, кто читает или использует наш код.

tpdi
источник
26

В SQL2008 BOL говорят, что в следующих выпусках будут нужны точки с запятой. Поэтому всегда используйте его.

Ссылка:

GSerg
источник
25

Вы должны использовать это.

Практика использования точки с запятой для завершения операторов является стандартной и фактически является требованием в некоторых других платформах баз данных. SQL Server требует точку с запятой только в определенных случаях, но в тех случаях, когда точка с запятой не требуется, ее использование не вызывает проблем. Я настоятельно рекомендую вам принять практику завершения всех утверждений точкой с запятой. Это не только улучшит читабельность вашего кода, но в некоторых случаях может сэкономить вам немного времени. (Когда точка с запятой требуется и не указана, сообщение об ошибке, выдаваемое SQL Server, не всегда ясно).

И самое главное:

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

Источник: Microsoft SQL Server 2012 T-SQL Основы Ицик Бен-Ган.


Примером того, почему вы всегда должны использовать, ;являются следующие два запроса (скопировано из этого поста ):

BEGIN TRY
    BEGIN TRAN
    SELECT 1/0 AS CauseAnException
    COMMIT
END TRY
BEGIN CATCH
    SELECT ERROR_MESSAGE()
    THROW
END CATCH

введите описание изображения здесь

BEGIN TRY
    BEGIN TRAN
    SELECT 1/0 AS CauseAnException;
    COMMIT
END TRY
BEGIN CATCH
    SELECT ERROR_MESSAGE();
    THROW
END CATCH

введите описание изображения здесь

gotqn
источник
7
Кажется, это сильный аргумент, что вы должны использовать точки с запятой (подкрепленные кавычками), но только в одном случае, где есть необходимость .
Грегор Томас
3
@ Грегор, если объявлено, что использование точек с запятой является обязательным и not using themне рекомендуется, вы должны их использовать. Если нет, есть риск страдать в будущем. Если вы не планируете обновлять / переключать работу и всегда собираетесь работать с SQL Server 2000, вы в безопасности :-)
gotqn
5
Хорошо , должен , я согласен. Но он первая линия вас ответ подчеркивает сусло , что это не так --- по крайней мере , еще нет.
Грегор Томас
2
Пример с точкой с запятой приводит Incorrect syntax near 'THROW'.к SQL Server 2008 (10.0.6241.0), который является версией, с которой мне приходится иметь дело на работе. Это работает, как показано в 2012 году. Меня убедили начать использовать точки с запятой из-за устаревания. Я не ожидаю, что это будет проблемой в 2008 году в большинстве случаев.
Pilot_51
1
Ваш ответ самый лучший! Это заслуживает гораздо больше голосов.
Стюарт
22

Если я правильно прочитал, для завершения операторов TSQL будет необходимо использовать точки с запятой. http://msdn.microsoft.com/en-us/library/ms143729%28v=sql.120%29.aspx

РЕДАКТИРОВАТЬ: Я нашел плагин для SSMS 2008R2, который отформатирует ваш скрипт и добавит точки с запятой. Я думаю, что это все еще в бета-версии, хотя ...

http://www.tsqltidy.com/tsqltidySSMSAddin.aspx

РЕДАКТИРОВАТЬ: я нашел еще лучший бесплатный инструмент / плагин под названием ApexSQL ... http://www.apexsql.com/

Spidermain50
источник
11

Личное мнение: используйте их только там, где они необходимы. (См. Ответ TheTXI выше для обязательного списка.)

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

[Это мнение относится к SQL Server. Другие базы данных могут иметь более строгие требования. Если вы пишете SQL для работы с несколькими базами данных, ваши требования могут отличаться.]

Как сказано выше в tpdi, «в сценарии, когда вы отправляете более одного оператора, он вам нужен». Это на самом деле не правильно. Тебе они не нужны.

PRINT 'Semicolons are optional'
PRINT 'Semicolons are optional'
PRINT 'Semicolons are optional';
PRINT 'Semicolons are optional';

Вывод:

Semicolons are optional
Semicolons are optional
Semicolons are optional
Semicolons are optional
Роб Гаррисон
источник
1
Что вы думаете об этой дискуссии? sqlservercentral.com/Forums/Topic636549-8-1.aspx (Yoy может использовать bugmenot@bugmenot.com: bugmenot, если у вас нет учетной записи)
Анвар Пинто
2
Я ценю, что вы четко заявили, что это только ваше мнение, однако я не думаю, что он дает хороший ответ, потому что он противоречит как документации Microsoft, так и стандарту ANSI. Я думаю, что это мнение будет лучше в комментарии. (Не пытаясь избить вас, вы имеете полное право на свое мнение об использовании точки с
запятой
4

Мне еще многое предстоит узнать о T-SQL, но при разработке некоторого кода для транзакции (и на основе кода на примерах из stackoverflow и других сайтов) я обнаружил случай, когда кажется, что точка с запятой требуется, и если она отсутствует, утверждение, кажется, не выполняется вообще, и никакой ошибки не возникает. Это, кажется, не охвачено ни в одном из приведенных выше ответов. (Это было с использованием MS SQL Server 2012.)

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

Так это

COMMIT TRANSACTION 

вне блока BEGIN TRY / END TRY работал нормально для фиксации транзакции, но внутри блока это должно было быть

COMMIT TRANSACTION;

Обратите внимание, что нет ошибок или предупреждений, а также указаний на то, что транзакция по-прежнему не завершена, пока не будет предпринята попытка закрыть вкладку запроса.

К счастью, это вызывает такую ​​огромную проблему, что сразу становится очевидно, что проблема есть. К сожалению, поскольку не сообщается об ошибке (синтаксис или иное), не сразу было понятно, в чем проблема.

В противоположность этому, ROLLBACK TRANSACTION одинаково хорошо работает в блоке BEGIN CATCH с точкой с запятой или без нее.

Возможно, в этом есть какая-то логика, но она кажется произвольной и «Алиса в стране чудес».

Мэтью Давидян
источник
Одной из возможных причин этого является COMMIT TRANSACTIONпринятие необязательного имени транзакции / точки сохранения (которое оно будет игнорировать). Без завершающей точки с запятой COMMIT TRANSACTIONможно использовать следующий символ, если он анализируется как идентификатор, что может радикально изменить семантику кода. Если это приводит к ошибке, CATCHзапуск может COMMITвыполняться без выполнения. И наоборот, хотя ROLLBACK TRANSACTIONи принимает необязательный идентификатор, подобный этому, ошибка при разборе там, скорее всего, в любом случае приведет к откату транзакции.
Йерун Мостерт
3

Оказывается , что точка с запятой не должны использоваться в сочетании с курсором операций: OPEN, FETCH, CLOSEи DEALLOCATE. Я просто потратил пару часов на это. Я внимательно посмотрел на BOL и заметил, что [;] не отображается в синтаксисе для этих операторов курсора !!

Итак, у меня было:

OPEN mycursor;

и это дало мне ошибку 16916.

Но:

OPEN mycursor

работал.

Rab
источник
2
Я не думаю, что это правильно. BOL не очень последовательн в упоминании точки с запятой в синтаксисе оператора, посмотрите, например, на SELECT. Плюс, я был свидетелем ОТКРЫТОГО некоего курсора работает нормально, то же самое для FETCH, CLOSE и DEALLOCATE ...
Валентино Вранкен
Это наводит на мысль об ошибке парсера. Какую версию SQL Server вы использовали / использовали?
Стюарт
0

При использовании оператора DISABLE или ENABLE TRIGGER в пакете, в котором есть другие операторы, оператор непосредственно перед ним должен заканчиваться точкой с запятой. В противном случае вы получите синтаксическую ошибку. Я сорвал свои волосы с этого ... И потом я наткнулся на этот пункт MS Connect о том же. Он закрыт, так как не исправит.

смотрите здесь

Ник V
источник
0

Примечание: это отвечает на вопрос в письменном виде, но не на проблему, как указано. Добавляя это здесь, так как люди будут искать это

Точка с запятой также используется ранее WITHв рекурсивных выражениях CTE:

;WITH Numbers AS
(
    SELECT n = 1
    UNION ALL
    SELECT n + 1
    FROM Numbers
    WHERE n+1 <= 10
)
SELECT n
FROM Numbers

Этот запрос сгенерирует CTE с именем Numbers, который состоит из целых чисел [1..10]. Это делается путем создания таблицы со значением только 1, а затем повторяющейся до достижения 10.

v010dya
источник
8
Технически не «до с», а после того, что раньше. Если с является первым оператором в пакете, точка с запятой не требуется.
Тор Хауген,
Это также не используется до СО. Это просто точка с запятой, которая завершает предыдущее утверждение. Кажется, некоторые люди решили, что точка с запятой должна быть здесь, так как это сценарий, в котором эта точка с запятой требуется. Почему эти люди решили, что это лучше, чем всегда заканчивать утверждения точкой с запятой, я понятия не имею.
Стюарт
0

Если вам нравится получать случайные ошибки Command Timeout в SQLServer, то оставьте точку с запятой в конце ваших строк CommandText.

Я не знаю, документировано ли это где-нибудь или это ошибка, но это происходит, и я узнал об этом из горького опыта.

У меня есть проверяемые и воспроизводимые примеры с использованием SQLServer 2008.

aka -> На практике всегда включайте терминатор, даже если вы просто отправляете один оператор в базу данных.

Аллан Махер
источник
Если вы получаете тайм-ауты для запроса, основанного только на том, есть ли в конце точка с запятой, то это почти наверняка вызвано наличием разных планов выполнения, поскольку они кэшируются путем сопоставления с точным текстом запроса, в том числе семантически несущественным такие вещи, как пробелы, комментарии и завершающая точка с запятой. Сама точка с запятой, тем не менее, будет совершенно невиновна в возникновении проблем с синхронизацией.
Йерун Мостерт
-2

Точки с запятой не всегда работают в составных операторах SELECT.

Сравните эти две разные версии тривиального составного оператора SELECT.

Код

DECLARE @Test varchar(35); 
SELECT @Test=
    (SELECT 
        (SELECT 
            (SELECT 'Semicolons do not always work fine.';););); 
SELECT @Test Test;

возвращается

Msg 102, Level 15, State 1, Line 5
Incorrect syntax near ';'.

Тем не менее, код

DECLARE @Test varchar(35)
SELECT @Test=
    (SELECT 
        (SELECT 
            (SELECT 'Semicolons do not always work fine.'))) 
SELECT @Test Test

возвращается

Test
-----------------------------------
Semicolons do not always work fine.

(1 row(s) affected)
Джон Фейлд
источник
11
[Год спустя]: Вау, я удивлен, никто еще не прокомментировал этот ответ! Конечно, это не будет работать, точки с запятой являются разделителями операторов, поэтому ваш код с точкой с запятой: 1- SELECT @ Test = (SELECT (SELECT (SELECT 'Точки с запятой не всегда работают нормально.'; - это не правильно утверждение 2-); - ни этот 3-); - ни тот, ни другой 4-); - ни одна точка с запятой не должна быть после трех скобок
PhpLou
1
Вы используете только точки с запятой для завершения операторов . Подзапрос не является утверждением. Заявления - это вещи, которые выполняются в последовательности. В вашем примере есть три утверждения: 1. DECLARE @ Test varchar (35) 2. SELECT @ Test = (SELECT (SELECT (SELECT 'Точки с запятой не всегда работают нормально.))) 3. SELECT @ Test Test
Стюарт