Коли я повинен використовувати крапки з комою в 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 - не перша заява в пакеті.


9
Чи THROWзаява Service Broker? Нам потрібно включити напівкрапку перед кидком у цьому прикладі:BEGIN ;THROW @Error, 'Invalid FundingID', 2; RETURN END
Кріс Уолш

1
Здається, вони в основному заохочують використання крапки з комою в цілому, вимагаючи цього перед усіма новими типами операторів, які були введені в останні роки. ( MERGEтеж наприклад). Як згадується в інших відповідях, у стандарті ANSI вони вимагаються
Марк Совул

2
@maurocam Я думаю, ви неправильно прочитали документ. Якщо ви подивитесь на це посилання, він говорить " Не закінчується операторами Transact-SQL крапкою з комою". застаріло.
Caltor

Як я бачу, це насправді не стосується питання про те, коли слід (на відміну від обов’язку ) використовувати крапку з комою.
Стюарт

81

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

Якщо ви надсилаєте лише одне твердження, технічно ви можете не обійтися термінатором оператора; у сценарії, оскільки ви надсилаєте кілька заяв, вам це потрібно.

На практиці завжди включайте термінатор, навіть якщо ви просто надсилаєте одне повідомлення в базу даних.

Редагувати: у відповідь на ці вимоги термінатори висловлювань не вимагають [конкретного RDBMS], хоча це може бути правдою, вони вимагаються стандартом ANSI SQL. Якщо у всіх програмуваннях ми можемо дотримуватися стандарту без втрати функціональності, ми повинні, оскільки тоді ні наш код, ні наші звички не пов'язані з одним власником постачальника.

З деякими компіляторами C можлива наявність основної недійсної віддачі, хоча стандарт вимагає головного повернення int. Але це робить наш код і ми самі менш портативними.

Найбільша складність у ефективному програмуванні - це не вивчення нових речей, це відучування шкідливих звичок. Наскільки ми можемо уникнути набуття шкідливих звичок в першу чергу, це виграш для нас, для нашого коду та для всіх, хто читає чи використовує наш код.


26

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

Довідка:


25

Ви повинні використовувати його.

Практика використання крапки з комою для завершення операторів є стандартною і фактично є вимогою у кількох інших платформах баз даних. SQL Server вимагає крапки з комою лише в окремих випадках, але у випадках, коли крапка з комою не потрібна, використання її не викликає проблем. Настійно рекомендую вам скористатися практикою завершення всіх операцій крапкою з комою. Це не тільки покращить читабельність вашого коду, але в деяких випадках може врятувати вам горе. (Коли потрібна крапка з комою та не вказана, повідомлення про помилку, яке виробляє SQL Server, не завжди є дуже зрозумілим.)

І найголовніше:

Документація на SQL Server вказує, що неприпинення операторів T-SQL крапкою з комою є застарілою функцією. Це означає, що довгостроковою метою є примусове використання крапки з комою в майбутній версії продукту. Це ще одна причина ввійти в звичку припиняти всі свої заяви, навіть там, де це наразі не потрібно.

Джерело: Основи T-SQL Microsoft SQL Server 2012 Іцік Бен-Ган.


Прикладом того, чому завжди потрібно використовувати, ;є наступні два запити (скопійовані з цієї публікації ):

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

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


7
Це здається вагомим аргументом, що ви повинні використовувати крапки з комою (підкріплені цитатами), але лише окремий випадок, коли є необхідність .
Грегор Томас

3
@Gregor, якщо буде оголошено, що використання крапки з комою є обов'язковим і 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

EDIT: Я знайшов плагін для SSMS 2008R2, який буде форматувати ваш сценарій і додавати крапки з комою. Я думаю, він все ще знаходиться в бета-версії ...

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

EDIT: Я знайшов ще кращий безкоштовний інструмент / плагін під назвою ApexSQL ... http://www.apexsql.com/


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, якщо у вас немає облікового запису)
Anwar Pinto

2
Я вдячний, що ви чітко заявили, що це лише ваша думка, однак я не думаю, що це дає хорошу відповідь, оскільки це суперечить як документації Microsoft, так і стандарту ANSI. Я думаю, що ця думка буде краще в коментарі. (Не намагаючись зірвати вас, ви повністю маєте право на свою думку щодо використання напівколонки!)
izzy

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і приймає такий необов'язковий ідентифікатор, помилка в розборі, швидше за все, призведе до того, що транзакція буде відмовлена ​​назад.
Jeroen

3

Виявляється , що точка з коми не повинні використовуватися в поєднанні з курсором операцій: OPEN,FETCH , CLOSEіDEALLOCATE . Я просто витратив на це пару годин. Я пильно подивився на BOL і помітив, що [;] не показано в синтаксисі цих курсорних висловлювань !!

Отже, у мене було:

OPEN mycursor;

і це дало мені помилку 16916.

Але:

OPEN mycursor

працювали.


2
Я не думаю, що це правильно. BOL не дуже послідовно згадує крапку з комою в синтаксисі оператора, дивіться, наприклад, SELECT. Плюс я був свідком OPEN someCursor; працює чудово, те саме для FETCH, CLOSE та DEALLOCATE ...
Валентино Вранкен

Це говорить про помилку з аналізатором. Яку версію SQL Server ви / використовували?
Стюарт


0

При використанні оператора DISABLE або ENABLE TRIGGER у партії, що містить інші оператори, оператор безпосередньо перед цим повинен закінчуватися крапкою з комою. В іншому випадку ви отримаєте синтаксичну помилку. Я вирвав волосся з цим ... І після цього я натрапив на цей елемент MS Connect про те саме. Він закритий, оскільки не виправиться.

дивіться тут


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.


8
Технічно не "раніше з", але після того, що відбувається раніше. Якщо з першим твердженням у пакеті, крапка з комою не потрібна.
Tor Haugen

Він також не використовується до З. Це лише крапка з комою, яка закінчує попереднє твердження. Здається, деякі люди вирішили, що крапка з комою повинна бути тут, оскільки це сценарій, коли вказана крапка з комою потрібна. Чому ці люди вирішили, що це краще, ніж завжди закінчувати заяви з крапками з комою, я не маю уявлення.
Стюарт

0

Якщо вам подобається отримувати випадкові помилки Timeout Timeout в SQLServer, тоді залиште крапку з комою в кінці рядків CommandText.

Я не знаю, чи це десь задокументовано чи це помилка, але це трапляється, і я дізнався це з гіркого досвіду.

Я маю підтверджувані та відтворювані приклади за допомогою SQLServer 2008.

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


Якщо ви отримуєте тайм-аути для запиту, що базується не на чому, окрім того, чи є крапка з комою в кінці, це майже напевно викликано наявністю різних планів виконання, оскільки вони кешовані шляхом відповідності точного тексту запиту, включаючи інакше семантично нерелевантні. такі речі, як пробіл, коментарі та закінчується крапкою з комою. Сама крапка з комою буде цілком невинна, якщо вона не спричинить жодних проблем із тимчасовою ознакою.
Jeroen

-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-4; - інакше ця крапка з комою повинна бути після трьох дужок
PhpLou

1
Ви використовуєте крапки з комою для завершення операторів . Підзапит - це не твердження. Заяви - це речі, які виконуються послідовно. У вашому прикладі є три твердження: 1. DECLARE @ Test varchar (35) 2. SELECT @ Test = (SELECT (SELECT (SELECT 'Точки з комою не завжди працюють нормально.'))) 3. SELECT @ Test Test
Stewart
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.