SQL Serverでセミコロンを使用する必要があるのはいつですか?


221

Web上のいくつかのコードとSQ​​L 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%クリーンブレークを行いたくない限り、これを強制する方法はありません。
Ian Kemp

回答:


152

Ken PowersによるSQLServerCentral.Comの記事から:

セミコロン

セミコロン文字はステートメントの終了文字です。これはANSI SQL-92標準の一部ですが、Transact-SQL内では使用されていません。実際、セミコロンに出くわすことなく、T-SQLを何年もコーディングすることが可能でした。

使用法

セミコロンを使用する必要がある状況は2つあります。最初の状況は、共通テーブル式(CTE)を使用する場合で、CTEはバッチの最初のステートメントではありません。2番目はService Brokerステートメントを発行する場所で、Service Brokerステートメントはバッチの最初のステートメントではありません。


9
あるTHROWService Brokerのステートメントは?我々は以前、この例ではスローにセミコロンを含める必要があります:BEGIN ;THROW @Error, 'Invalid FundingID', 2; RETURN END
クリス・ウォルシュ

1
近年導入されたすべての新しいステートメントタイプの前にセミコロンを要求することにより、基本的にセミコロンの使用を奨励しているようです。(MERGE例も)。他の回答で述べたように、ANSI標準では必須です
Mark Sowul

2
@maurocamドキュメントを間違って読んだと思います。そのリンクを見ると、「Transact-SQLステートメントをセミコロン終わらせていない」と表示されています。廃止予定です。
Caltor、

私が見ているように、これはセミコロンをいつ使用する必要があるの必須ではない)の問題には実際には対応していません。
スチュワート

81

デフォルトでは、SQLステートメントはセミコロンで終了します。新しいステートメントターミネータを(まれに)設定していない限り、セミコロンを使用してステートメントを終了します。

ステートメントを1つだけ送信する場合、技術的にはステートメントターミネータを省略できます。スクリプトでは、複数のステートメントを送信するときに必要になります。

実際には、データベースにステートメントを1つだけ送信する場合でも、常にターミネータを含めます。

編集:[特定のRDBMS]ではステートメントターミネーターは不要であると述べていることに対応して、それは当てはまる場合がありますが、ANSI SQL標準では必須です。すべてのプログラミングにおいて、機能を失うことなく標準に準拠できる場合は、その必要があります。それは、コードも習慣も、1つの専有ベンダーに結び付けられていないためです。

一部のCコンパイラでは、標準でメインがintを返すように要求している場合でも、メインの戻りが無効になる可能性があります。しかし、これを行うと、コード自体、および移植性が低下します。

効果的なプログラミングの最大の困難は、新しいことを学ぶことではなく、悪い習慣を身につけないことです。そもそも悪い習慣を身につけないようにすることができる範囲で、それは私たちにとって、私たちのコードにとって、そして私たちのコードを読んだり使用したりする人にとっての勝利です。



25

あなたそれを使わなければなりません

セミコロンを使用してステートメントを終了する方法は標準であり、実際には他のいくつかのデータベースプラットフォームでは要件となっています。SQL Serverは特定の場合にのみセミコロンを必要としますが、セミコロンが不要な場合は、セミコロンを使用しても問題は発生しません。すべてのステートメントをセミコロンで終了する方法を採用することを強くお勧めします。これにより、コードが読みやすくなるだけでなく、場合によっては、悲しみを和らげることができます。(セミコロンが必要で指定されていない場合、SQL Serverが生成するエラーメッセージは必ずしも明確ではありません。)

そして最も重要なこと:

SQL Serverのドキュメントには、T-SQLステートメントをセミコロンで終了しないことは非推奨の機能であると記載されています。つまり、長期的な目標は、製品の将来のバージョンでセミコロンの使用を強制することです。これが、現在必要とされていない場合でも、すべてのステートメントを終了する癖をつけるもう1つの理由です。

出典: Itzik Ben-GanによるMicrosoft SQL Server 2012 T-SQLの基礎


常に使用する必要がある理由の例;は、次の2つのクエリ(この投稿からコピー)です。

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
これはセミコロン(引用符でバックアップ)使用する必要があるという強力な議論のようですが、mustが存在するのは1つのケースのみです。
グレゴールトーマス

3
@Gregor、セミコロンの使用が必須でnot using them非推奨のテクニックであることが発表されている場合は、それらを使用する必要があります。そうでなければ、将来苦しむリスクがあります。ジョブのアップグレード/切り替えを計画しておらず、常にSQL Server 2000で作業する場合は、安全です:-)
gotqn

5
そうね、そうね。しかし、彼の最初の行の答え、を強調しています、それは事実ではありません---少なくともまだです。
Gregor Thomas

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/


11

個人的な意見:必要な場合にのみ使用してください。(必要なリストについては、上記のTXIの回答を参照してください。)

コンパイラはそれらを必要としないので、それらをすべて配置できます、なぜですか?コンパイラは、どこで忘れたかを教えてくれないので、一貫性のない使用法になります。

[この意見は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を使用していました。)

トランザクションを希望どおりに機能させると、その周りにtry-catchを配置することにしました。エラーが発生した場合は、ロールバックされます。これを実行した後でのみ、トランザクションはコミットされませんでした(SSMSは、コミットされていないトランザクションがあることを警告する素敵なメッセージでウィンドウを閉じようとしたときにこれを確認します。

したがって、この

COMMIT TRANSACTION 

BEGIN TRY / END TRYブロックの外側はトランザクションをコミットするためにうまく機能しましたが、ブロックの内側では

COMMIT TRANSACTION;

エラーや警告は表示されず、クエリタブを閉じようとするまでトランザクションがまだコミットされていないことを示すものではありません。

幸いなことに、これは非常に大きな問題を引き起こし、問題があることがすぐに明らかになります。残念ながら、エラー(構文など)は報告されていないため、問題が何であるかはすぐにはわかりませんでした。

逆に、ROLLBACK TRANSACTIONは、セミコロンの有無にかかわらず、BEGIN CATCHブロックでも同じように機能するようです。

これにはいくらかの論理があるかもしれませんが、それは恣意的で不思議の国のアリスらしいです。


これの考えられる原因の1つCOMMIT TRANSACTIONは、オプションのトランザクション/保存ポイント名(これは無視されます)を受け入れることです。終了セミコロンがないCOMMIT TRANSACTIONと、識別子として解析される場合、次のシンボルを食べる可能性があり、コードのセマンティクスを根本的に変える可能性があります。これによりエラーが発生したCATCH場合、はCOMMIT実行されずにトリガーされることがあります。逆に、ROLLBACK TRANSACTIONこのようなオプションの識別子も受け入れますが、そこでの解析エラーは、トランザクションがとにかくロールバックされる可能性が高いです。
Jeroen Mostert

3

:セミコロンがカーソル操作と連動して使用すべきではないと思われるOPENFETCHCLOSEDEALLOCATE。私はこれで数時間を無駄にしました。BOLを詳しく調べたところ、[;]がこれらのカーソルステートメントの構文に表示されていないことに気づきました。

だから私は持っていました:

OPEN mycursor;

これにより、エラー16916が発生しました。

だが:

OPEN mycursor

働いた。


2
これは正しいとは思いません。BOLは、ステートメント構文でセミコロンに言及することに一貫性がありません。たとえば、SELECTを見てください。さらに、OPEN someCursorを目撃しました。正常に動作し、FETCH、CLOSE、DEALLOCATEでも同じです。–
Valentino

これは、パーサーのバグを示唆しています。SQL Serverのどのバージョンを使用していますか?
スチュワート

2

よると、Transact-SQLの構文規則(のTransact-SQL)(MSDN)

Transact-SQLステートメントの終了文字。セミコロンは、このバージョンのSQL Serverのほとんどのステートメントでは必要ありませんが、将来のバージョンでは必要になるでしょう。

(@gerryLowryのコメントも参照)


0

他のステートメントが含まれているバッチでDISABLEまたはENABLE TRIGGERステートメントを使用する場合、その直前のステートメントはセミコロンで終了する必要があります。そうしないと、構文エラーが発生します。私はこれで髪を引きちぎりました...その後、私はこのMSコネクトアイテムに同じことについて偶然見つけました。修正されないため、クローズされています。

こちらをご覧ください


0

注:これは書かれた質問に答えますが、述べられた問題には答えません。人々がそれを探すので、ここに追加します

セミコロンは、以前WITHに再帰CTEステートメントでも使用されています。

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

このクエリは、整数[1..10]で構成されるNumbersというCTEを生成します。これは、値が1のテーブルのみを作成し、10に達するまで再帰的に実行されます。


8
技術的には「前に」ではなく、前に何が来た後でも。withがバッチの最初のステートメントである場合、セミコロンは不要です。
Tor Haugen

WITHの前に使用されません。これは、前のステートメントを終了するセミコロンにすぎません。これはセミコロンが必要なシナリオであるため、セミコロンをここに配置する必要があると判断した人もいるようです。これらの人々がこれが常にセミコロンでステートメントを終了させるよりも優れていると決定した理由は、私にはわかりません。
スチュワート

0

SQLServerでランダムなコマンドタイムアウトエラーが発生する場合は、CommandText文字列の最後のセミコロンを省略してください。

これがどこに文書化されているのか、それともバグなのかはわかりませんが、実際に起こり、苦い経験からこれを学びました。

SQLServer 2008を使用して検証および再現可能な例があります。

別名-> 実際には、データベースにステートメントを1つだけ送信する場合でも、常にターミネータを含めます。


最後にセミコロンがあるかどうかにのみ基づいてクエリのタイムアウトを取得している場合、それはほとんどの場合、異なる実行プランがあるために発生します。それらは、意味的に関連のないものを含め、正確なクエリテキストでのマッチングによってキャッシュされるためです。空白、コメント、終了セミコロンなど。ただし、セミコロン自体は、タイミングの問題を引き起こすことはまったくありません。
Jeroen Mostert

-2

セミコロンは常に複合SELECTステートメントで機能するとは限りません。

単純な複合SELECTステートメントのこれら2つの異なるバージョンを比較します。

コード

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年後]:わあ、まだこの回答について誰もコメントしていません。もちろん、機能しません。セミコロンはステートメントの区切り文字であるため、セミコロンを含むコードは次のようになります。ステートメント2-);-どちらでもない3-);-どちらでもない4-);
PhpLou 2015年

1
セミコロンはステートメントの終了にのみ使用します。サブクエリはステートメントではありません。ステートメントは、順番に実行されるものです。あなたの例では、3つのステートメントがあります。1. DECLARE @ Test varchar(35)2. SELECT @ Test =(SELECT(SELECT(SELECT 'SELECT' Semicolons do not work like。 ')))3. SELECT @ Test Test
Stewart
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.