Wann sollte ich Semikolons in SQL Server verwenden?

221

Beim Überprüfen von Code im Web und von SQL Server Management Studio generierten Skripten habe ich festgestellt, dass einige Anweisungen mit einem Semikolon beendet werden.

Wann sollte ich es verwenden?

Anwar Pinto
quelle
23
SQL Server 2008 R2 msdn.microsoft.com/en-us/library/ms177563.aspx "Transact-SQL- Syntaxkonventionen (Transact-SQL)" ; == Transact-SQL-Anweisungsabschluss. Obwohl das Semikolon für die meisten Anweisungen in dieser Version von SQL Server nicht erforderlich ist , wird es in einer zukünftigen Version benötigt .
GerryLowry
2
Obwohl sie behaupten, dass in einer zukünftigen Version ein Semikolon erforderlich sein wird, wird dies niemals wahr werden. Sie können dies aus Kompatibilitätsgründen niemals vorschreiben. Es würde ungefähr 100% der Anwendungen brechen.
usr
1
Es ist jetzt 2019 und in der neuesten Version von SQL Server wird noch kein Semikolon akzeptiert. Wie @usr sagt, gibt es keine Möglichkeit, dies durchzusetzen, es sei denn, Microsoft möchte eine 100% saubere Pause einlegen.
Ian Kemp

Antworten:

152

Aus einem SQLServerCentral.Com- Artikel von Ken Powers:

Das Semikolon

Das Semikolon ist ein Anweisungsabschluss. Es ist Teil des ANSI SQL-92-Standards, wurde jedoch nie in Transact-SQL verwendet. In der Tat war es möglich, T-SQL jahrelang zu codieren, ohne jemals auf ein Semikolon zu stoßen.

Verwendung

Es gibt zwei Situationen, in denen Sie das Semikolon verwenden müssen. In der ersten Situation verwenden Sie einen Common Table Expression (CTE), und der CTE ist nicht die erste Anweisung im Stapel. In der zweiten Anweisung geben Sie eine Service Broker-Anweisung aus, und die Service Broker-Anweisung ist nicht die erste Anweisung im Stapel.

TheTXI
quelle
9
Ist THROWeine Service Broker-Anweisung? Wir müssen ein Semikolon vor einem Wurf in dieses Beispiel BEGIN ;THROW @Error, 'Invalid FundingID', 2; RETURN END
Chris Walsh
1
Scheint, als würden sie die Verwendung des Semikolons im Allgemeinen fördern, indem sie es vor allen neuen Anweisungstypen verlangen, die in den letzten Jahren eingeführt wurden. ( MERGEauch zum Beispiel). Wie in anderen Antworten erwähnt, sind sie im ANSI-Standard erforderlich
Mark Sowul
2
@maurocam Ich denke, Sie haben das Dokument falsch gelesen. Wenn Sie zu diesem Link sehen , sagt er „ nicht enden Transact-SQL - Anweisungen mit einem Semikolon.“ ist veraltet.
Caltor
Aus meiner Sicht geht es hier nicht wirklich um die Frage, wann man ein Semikolon verwenden sollte (im Gegensatz zu muss ).
Stewart
81

Standardmäßig werden SQL-Anweisungen mit Semikolons abgeschlossen. Sie verwenden ein Semikolon, um Anweisungen zu beenden, es sei denn, Sie haben (selten) einen neuen Anweisungsabschluss festgelegt.

Wenn Sie nur eine Anweisung senden, können Sie technisch auf den Anweisungsabschluss verzichten. Wenn Sie in einem Skript mehr als eine Anweisung senden, benötigen Sie diese.

Fügen Sie in der Praxis immer den Terminator ein, auch wenn Sie nur eine Anweisung an die Datenbank senden.

Bearbeiten: Als Antwort auf die Aussage, dass Anweisungsabschlusszeichen von [bestimmten RDBMS] nicht benötigt werden, obwohl dies wahr sein kann, werden sie vom ANSI SQL Standard benötigt. Wenn wir bei der gesamten Programmierung einen Standard ohne Funktionsverlust einhalten können, sollten wir dies tun, da dann weder unser Code noch unsere Gewohnheiten an einen proprietären Anbieter gebunden sind.

Bei einigen C-Compilern ist es möglich, dass die Hauptrückgabe ungültig ist, obwohl der Standard erfordert, dass main int zurückgibt. Dies macht unseren Code und uns selbst jedoch weniger portabel.

Die größte Schwierigkeit beim effektiven Programmieren besteht nicht darin, neue Dinge zu lernen, sondern schlechte Gewohnheiten zu verlernen. In dem Maße, in dem wir vermeiden können, schlechte Gewohnheiten zu erlangen, ist dies ein Gewinn für uns, für unseren Code und für jeden, der unseren Code liest oder verwendet.

tpdi
quelle
25

Sie müssen es verwenden.

Die Verwendung eines Semikolons zum Beenden von Anweisungen ist Standard und in mehreren anderen Datenbankplattformen erforderlich. SQL Server benötigt das Semikolon nur in bestimmten Fällen. In Fällen, in denen kein Semikolon erforderlich ist, verursacht die Verwendung eines Semikolons keine Probleme. Ich empfehle Ihnen dringend, alle Anweisungen mit einem Semikolon zu beenden. Dies verbessert nicht nur die Lesbarkeit Ihres Codes, sondern kann Ihnen in einigen Fällen auch Kummer ersparen. (Wenn ein Semikolon erforderlich ist und nicht angegeben wird, ist die Fehlermeldung, die SQL Server erzeugt, nicht immer sehr deutlich.)

Und das Wichtigste:

In der SQL Server-Dokumentation wird angegeben, dass das Nichtbeenden von T-SQL-Anweisungen mit einem Semikolon eine veraltete Funktion ist. Dies bedeutet, dass das langfristige Ziel darin besteht, die Verwendung des Semikolons in einer zukünftigen Version des Produkts zu erzwingen. Dies ist ein weiterer Grund, sich daran zu gewöhnen, alle Ihre Aussagen zu beenden, auch wenn dies derzeit nicht erforderlich ist.

Quelle: Microsoft SQL Server 2012 T-SQL-Grundlagen von Itzik Ben-Gan.


Ein Beispiel dafür, warum Sie immer verwenden müssen, ;sind die folgenden zwei Abfragen (aus diesem Beitrag kopiert ):

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

Geben Sie hier die Bildbeschreibung ein

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

Geben Sie hier die Bildbeschreibung ein

gotqn
quelle
7
Dies scheint ein starkes Argument zu sein , dass Sie sollten Semikolons (gesichert durch die Anführungszeichen), aber nur einen einzigen Fall , wo es einen verwenden muss .
Gregor Thomas
3
@ Gregor, wenn angekündigt wird, dass die Verwendung von Semikolons ein Muss und not using themeine veraltete Technik ist, sollten Sie sie verwenden. Wenn nicht, besteht die Gefahr, in Zukunft zu leiden. Wenn Sie nicht vorhaben, den Job zu aktualisieren / zu wechseln und immer mit SQL Server 2000 arbeiten, sind Sie sicher :-)
gotqn
5
Richtig, sollte ich zustimmen. Aber die erste Zeile Ihrer Antwort betont das Muss , was nicht der Fall ist - zumindest noch nicht.
Gregor Thomas
2
Das Beispiel mit Semikolons führt Incorrect syntax near 'THROW'.zu SQL Server 2008 (10.0.6241.0), der Version, mit der ich mich bei der Arbeit befassen muss. Es funktioniert wie im Jahr 2012 gezeigt. Ich war überzeugt, aufgrund der Abwertung Semikolons zu verwenden. Ich gehe nicht davon aus, dass es 2008 die meiste Zeit ein Problem sein wird.
Pilot_51
1
Ihre Antwort ist bei weitem die beste! Es verdient weit mehr positive Stimmen.
Stewart
22

Wenn ich dies richtig lese, müssen Semikolons zum Beenden von TSQL-Anweisungen verwendet werden. http://msdn.microsoft.com/en-us/library/ms143729%28v=sql.120%29.aspx

BEARBEITEN: Ich habe ein Plug-In für SSMS 2008R2 gefunden, das Ihr Skript formatiert und die Semikolons hinzufügt. Ich denke, es ist noch in der Beta ...

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

EDIT: Ich habe ein noch besseres kostenloses Tool / Plugin namens ApexSQL gefunden ... http://www.apexsql.com/

Spidermain50
quelle
11

Persönliche Meinung: Verwenden Sie sie nur dort, wo sie benötigt werden. (Die erforderliche Liste finden Sie in der obigen Antwort von TheTXI.)

Da der Compiler sie nicht benötigen, Sie können sie überall setzen, aber warum? Der Compiler teilt Ihnen nicht mit, wo Sie einen vergessen haben, sodass Sie am Ende eine inkonsistente Verwendung haben.

[Diese Meinung gilt speziell für SQL Server. Andere Datenbanken stellen möglicherweise strengere Anforderungen. Wenn Sie SQL für die Ausführung auf mehreren Datenbanken schreiben, können Ihre Anforderungen variieren.]

tpdi sagte oben: "Wenn Sie in einem Skript mehr als eine Anweisung senden, benötigen Sie diese." Das stimmt eigentlich nicht. Du brauchst sie nicht.

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

Ausgabe:

Semicolons are optional
Semicolons are optional
Semicolons are optional
Semicolons are optional
Rob Garrison
quelle
1
Was denkst du über diese Diskussion? sqlservercentral.com/Forums/Topic636549-8-1.aspx (Yoy kann [email protected] verwenden: bugmenot, wenn Sie kein Konto haben)
Anwar Pinto
2
Ich schätze, dass Sie klar gesagt haben, dass dies nur Ihre Meinung ist, aber ich denke nicht, dass dies eine gute Antwort ist, da es sowohl mit der Microsoft-Dokumentation als auch mit dem ANSI-Standard in Konflikt steht. Ich würde denken, dass diese Meinung in einem Kommentar besser wäre. (Sie versuchen nicht, Sie zu verprügeln, Sie haben ein Recht auf Ihre Meinung zur Verwendung von
Semikolons
4

Ich muss noch viel über T-SQL lernen, aber als ich Code für eine Transaktion ausarbeitete (und Code anhand von Beispielen aus Stackoverflow und anderen Sites basierte), fand ich einen Fall, in dem ein Semikolon erforderlich zu sein scheint und wenn es fehlt, Die Anweisung scheint überhaupt nicht ausgeführt zu werden und es wird kein Fehler ausgegeben. Dies scheint in keiner der obigen Antworten behandelt zu werden. (Dies war mit MS SQL Server 2012.)

Nachdem die Transaktion so funktioniert hatte, wie ich es wollte, habe ich beschlossen, sie mit einem Try-Catch zu versehen, damit sie bei Fehlern zurückgesetzt wird. Erst danach wurde die Transaktion nicht festgeschrieben (SSMS bestätigt dies, wenn versucht wird, das Fenster mit einer netten Nachricht zu schließen, die Sie darauf hinweist, dass eine nicht festgeschriebene Transaktion vorliegt.

Also das

COMMIT TRANSACTION 

außerhalb eines BEGIN TRY / END TRY-Blocks funktionierte das Festschreiben der Transaktion einwandfrei, aber innerhalb des Blocks musste es sein

COMMIT TRANSACTION;

Beachten Sie, dass kein Fehler oder keine Warnung bereitgestellt wird und kein Hinweis darauf vorliegt, dass die Transaktion bis zum Versuch, die Registerkarte "Abfrage" zu schließen, immer noch nicht festgeschrieben ist.

Glücklicherweise verursacht dies ein so großes Problem, dass sofort klar ist, dass es ein Problem gibt. Da leider kein Fehler (Syntax oder anderweitig) gemeldet wird, war das Problem nicht sofort ersichtlich.

Im Gegensatz dazu scheint ROLLBACK TRANSACTION im BEGIN CATCH-Block mit oder ohne Semikolon gleich gut zu funktionieren.

Es mag eine Logik dafür geben, aber es fühlt sich willkürlich und Alice im Wunderland an.

Matthew Davidian
quelle
Eine mögliche Ursache hierfür ist, dass COMMIT TRANSACTIONein optionaler Transaktions- / Speicherpunktname akzeptiert wird (der ignoriert wird). Ohne ein abschließendes Semikolon COMMIT TRANSACTIONkann das nächste Symbol gegessen werden, wenn es als Bezeichner analysiert wird, wodurch die Semantik des Codes radikal geändert werden kann. Wenn dies dann zu einem Fehler führt, CATCHkann der ausgelöst werden, ohne dass der COMMITjemals ausgeführt wurde. Umgekehrt ROLLBACK TRANSACTIONakzeptiert ein Fehler beim Parsen , obwohl er auch einen optionalen Bezeichner wie diesen akzeptiert, höchstwahrscheinlich, dass die Transaktion trotzdem zurückgesetzt wird.
Jeroen Mostert
3

Es scheint , dass Semikolons sollte nicht in Verbindung mit Cursor - Operationen verwendet werden: OPEN, FETCH, CLOSEund DEALLOCATE. Ich habe nur ein paar Stunden damit verschwendet. Ich habe mir die BOL genau angesehen und festgestellt, dass [;] in der Syntax für diese Cursoranweisungen nicht angezeigt wird !!

So hatte ich:

OPEN mycursor;

und das gab mir Fehler 16916.

Aber:

OPEN mycursor

hat funktioniert.

rab
quelle
2
Ich denke nicht, dass das richtig ist. Die BOL ist nicht sehr konsistent, wenn es darum geht, das Semikolon in der Anweisungssyntax zu erwähnen. Schauen Sie sich zum Beispiel SELECT an. Außerdem habe ich OPEN someCursor gesehen. funktioniert gut, das gleiche gilt für FETCH, CLOSE und DEALLOCATE ...
Valentino Vranken
Das deutet auf einen Fehler mit dem Parser hin. Welche Version von SQL Server verwenden Sie / haben Sie verwendet?
Stewart
2

Gemäß Transact-SQL-Syntaxkonventionen (Transact-SQL) (MSDN)

Transact-SQL-Anweisungsabschluss. Obwohl das Semikolon für die meisten Anweisungen in dieser Version von SQL Server nicht erforderlich ist, wird es in einer zukünftigen Version benötigt.

(siehe auch den Kommentar von @gerryLowry)

Alan B.
quelle
0

Wenn Sie eine DISABLE- oder ENABLE TRIGGER-Anweisung in einem Stapel verwenden, der andere Anweisungen enthält, muss die Anweisung unmittelbar davor mit einem Semikolon enden. Andernfalls wird ein Syntaxfehler angezeigt. Ich habe mir mit diesem die Haare ausgerissen ... Und danach bin ich über dieses MS Connect-Objekt über dasselbe gestolpert. Es ist geschlossen, da es nicht repariert werden kann.

siehe hier

Nick V.
quelle
0

Hinweis: Dies beantwortet die Frage wie geschrieben, aber nicht das angegebene Problem. Fügen Sie es hier hinzu, da die Leute danach suchen werden

Semikolon wird zuvor auch WITHin rekursiven CTE-Anweisungen verwendet:

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

Diese Abfrage generiert einen CTE namens Numbers, der aus Ganzzahlen besteht [1..10]. Dazu erstellen Sie eine Tabelle mit nur dem Wert 1 und wiederholen diese, bis Sie 10 erreichen.

v010dya
quelle
8
Technisch nicht "vorher mit", sondern nach dem, was vorher mit kommt. Wenn with die erste Anweisung im Stapel ist, ist kein Semikolon erforderlich.
Tor Haugen
Es ist nicht auch vor WITH verwendet. Dies ist nur das Semikolon, das die vorherige Anweisung beendet. Es scheint, dass einige Leute entschieden haben, dass das Semikolon hier sein sollte, da dies ein Szenario ist, in dem dieses Semikolon erforderlich ist. Warum diese Leute entschieden haben, dass dies besser ist, als Anweisungen immer mit Semikolons zu beenden, weiß ich nicht.
Stewart
0

Wenn Sie zufällige Command Timeout- Fehler in SQLServer erhalten möchten, lassen Sie das Semikolon am Ende Ihrer CommandText-Zeichenfolgen weg.

Ich weiß nicht, ob dies irgendwo dokumentiert ist oder ob es sich um einen Fehler handelt, aber es passiert und ich habe dies aus bitterer Erfahrung gelernt.

Ich habe überprüfbare und reproduzierbare Beispiele mit SQLServer 2008.

aka -> Fügen Sie in der Praxis immer den Terminator ein, auch wenn Sie nur eine Anweisung an die Datenbank senden.

Allan Maher
quelle
Wenn Sie Zeitüberschreitungen für eine Abfrage erhalten, die auf nichts anderem als der Frage basiert, ob am Ende ein Semikolon steht oder nicht, liegt dies mit ziemlicher Sicherheit an unterschiedlichen Ausführungsplänen, da diese durch Abgleich mit genauem Abfragetext zwischengespeichert werden, auch wenn dies ansonsten semantisch irrelevant ist Dinge wie Leerzeichen, Kommentare und ein abschließendes Semikolon. Das Semikolon selbst ist jedoch völlig unschuldig, wenn es zu Zeitproblemen kommt.
Jeroen Mostert
-2

Semikolons funktionieren nicht immer in zusammengesetzten SELECT-Anweisungen.

Vergleichen Sie diese beiden unterschiedlichen Versionen einer trivialen zusammengesetzten SELECT-Anweisung.

Der Code

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

kehrt zurück

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

Allerdings der Code

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

kehrt zurück

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

(1 row(s) affected)
John Feild
quelle
11
[Ein Jahr später]: Wow, ich bin überrascht, dass noch niemand diese Antwort kommentiert hat! Natürlich funktioniert es nicht, Semikolons sind Anweisungstrennzeichen, daher lautet Ihr Code mit den Semikolons: 1- SELECT @ Test = (SELECT (SELECT (SELECT 'Semikolons funktionieren nicht immer gut.'; - dies ist nicht korrekt Aussage 2-); - weder ist dies 3-); - noch diese 4-); - Weder das Semikolon sollte nach den 3 Klammern stehen
PhpLou
1
Sie verwenden nur Semikolons, um Anweisungen zu beenden . Eine Unterabfrage ist keine Aussage. Anweisungen sind Dinge, die nacheinander ausgeführt werden. In Ihrem Beispiel gibt es drei Anweisungen: 1. DECLARE @ Test varchar (35) 2. SELECT @ Test = (SELECT (SELECT (SELECT 'Semikolons funktionieren nicht immer gut.')) 3. SELECT @ Test Test
Stewart