Quando dovrei usare i punti e virgola in SQL Server?


221

Durante la verifica del codice sul Web e degli script generati da SQL Server Management Studio ho notato che alcune istruzioni sono terminate con un punto e virgola.

Quindi quando dovrei usarlo?


23
Msdn.microsoft.com/en-us/library/ms177563.aspx di SQL Server 2008 R2 "Convenzioni della sintassi Transact-SQL (Transact-SQL)" ; == Terminator istruzione Transact-SQL. Sebbene il punto e virgola non sia richiesto per la maggior parte delle istruzioni in questa versione di SQL Server, sarà richiesto in una versione futura .
gerryLowry,

2
Anche se sostengono che in una versione futura sarà richiesto un punto e virgola, questo non diventerà mai realtà. Non possono mai imporlo per motivi di compatibilità. Si romperebbe circa il 100% delle applicazioni.
usr

1
È ora il 2019 e nessun punto e virgola è ancora felicemente accettato nell'ultima versione di SQL Server. Come dice @usr, a meno che Microsoft non voglia fare una pausa pulita al 100%, non c'è modo di far valere questo.
Ian Kemp il

Risposte:


152

Da un articolo di SQLServerCentral.Com di Ken Powers:

Il punto e virgola

Il carattere punto e virgola è un terminatore di istruzione. Fa parte dello standard ANSI SQL-92, ma non è mai stato utilizzato in Transact-SQL. In effetti, è stato possibile codificare T-SQL per anni senza mai incontrare un punto e virgola.

uso

Esistono due situazioni in cui è necessario utilizzare il punto e virgola. La prima situazione è quella in cui si utilizza Common Table Expression (CTE) e il CTE non è la prima istruzione nel batch. Il secondo è dove si emette un'istruzione di Service Broker e l'istruzione di Service Broker non è la prima istruzione nel batch.


9
È THROWuna dichiarazione di Service Broker? In questo esempio dobbiamo includere un punto e virgola prima di un lancio:BEGIN ;THROW @Error, 'Invalid FundingID', 2; RETURN END
Chris Walsh,

1
Sembra che stiano fondamentalmente incoraggiando l'uso del punto e virgola in generale, richiedendolo prima di tutti i nuovi tipi di dichiarazione che sono stati introdotti negli ultimi anni. ( MERGEanche per esempio). Come menzionato in altre risposte, nello standard ANSI sono richiesti
Mark Sowul il

2
@maurocam Penso che tu abbia letto il documento in modo errato. Se guardi quel link, dice " Non terminare le istruzioni Transact-SQL con un punto e virgola." è deprecato.
Caltor,

A mio avviso, questo non affronta realmente la questione di quando si dovrebbe (al contrario di un must ) usare un punto e virgola.
Stewart,

81

Per impostazione predefinita, le istruzioni SQL sono terminate con punto e virgola. Si utilizza un punto e virgola per terminare le istruzioni a meno che non si sia (raramente) impostato un nuovo terminatore di istruzioni.

Se stai inviando una sola istruzione, tecnicamente puoi rinunciare al terminatore delle istruzioni; in uno script, poiché stai inviando più di un'istruzione, ne hai bisogno.

In pratica, includere sempre il terminatore anche se si sta semplicemente inviando un'istruzione al database.

Modifica: in risposta a quelli che dicono che i terminatori di istruzioni non sono richiesti da [particolare RDBMS], sebbene ciò sia vero, sono richiesti dallo standard ANSI SQL. In tutta la programmazione, se siamo in grado di aderire a uno standard senza perdita di funzionalità, dovremmo, perché allora né il nostro codice né le nostre abitudini sono legati a un fornitore proprietario.

Con alcuni compilatori C, è possibile avere il vuoto return principale, anche se lo Standard richiede main per restituire int. Ma farlo rende il nostro codice e noi stessi meno portabile.

La più grande difficoltà nella programmazione efficacemente non è imparare cose nuove, è disimparare cattive abitudini. Nella misura in cui possiamo evitare di acquisire cattive abitudini in primo luogo, è una vittoria per noi, per il nostro codice e per chiunque legga o utilizzi il nostro codice.



25

È necessario usarlo.

La pratica di utilizzare un punto e virgola per terminare le istruzioni è standard e in realtà è un requisito in molte altre piattaforme di database. SQL Server richiede il punto e virgola solo in casi particolari, ma nei casi in cui non è richiesto un punto e virgola, l'utilizzo di uno non causa problemi. Consiglio vivamente di adottare la pratica di terminare tutte le istruzioni con un punto e virgola. Questo non solo migliorerà la leggibilità del tuo codice, ma in alcuni casi ti farà risparmiare un po 'di dolore. (Quando è richiesto un punto e virgola e non è specificato, il messaggio di errore generato da SQL Server non è sempre molto chiaro.)

E soprattutto:

La documentazione di SQL Server indica che non terminare le istruzioni T-SQL con un punto e virgola è una funzione obsoleta. Ciò significa che l'obiettivo a lungo termine è imporre l'uso del punto e virgola in una versione futura del prodotto. Questo è un motivo in più per prendere l'abitudine di terminare tutte le tue dichiarazioni, anche dove attualmente non è richiesto.

Fonte: Fondamenti T-SQL di Microsoft SQL Server 2012 di Itzik Ben-Gan.


Un esempio del motivo per cui è sempre necessario utilizzare ;sono le seguenti due query (copiate da questo post ):

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

inserisci qui la descrizione dell'immagine

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

inserisci qui la descrizione dell'immagine


7
Questo sembra essere un forte argomento secondo cui dovresti usare i punti e virgola (supportati dalle virgolette), ma solo un singolo caso in cui è necessario .
Gregor Thomas

3
@Gregor, se viene annunciato che l'uso del punto e virgola è un must ed not using themè una tecnica deprecata, dovresti usarli. Altrimenti, c'è il rischio di soffrire in futuro. Se non si prevede di aggiornare / cambiare lavoro e si lavora sempre con SQL Server 2000, si è al sicuro :-)
gotqn

5
Bene, dovrei , sono d'accordo. Ma la prima riga della tua risposta enfatizza must , il che non è il caso --- almeno non ancora.
Gregor Thomas

2
L'esempio con punti e virgola si traduce in Incorrect syntax near 'THROW'.SQL Server 2008 (10.0.6241.0), che è la versione che devo affrontare al lavoro. Funziona come mostrato nel 2012. Sono stato convinto di iniziare a utilizzare i punti e virgola a causa della deprecazione. Non mi aspetto che sarebbe un problema per il 2008 la maggior parte delle volte.
Pilot_51,

1
La tua risposta è di gran lunga la migliore! Merita molti più voti.
Stewart

22

Se lo leggo correttamente, sarà necessario utilizzare i punti e virgola per terminare le istruzioni TSQL. http://msdn.microsoft.com/en-us/library/ms143729%28v=sql.120%29.aspx

EDIT: ho trovato un plug-in per SSMS 2008R2 che formatterà il tuo script e aggiungerà i punti e virgola. Penso che sia ancora in beta però ...

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

EDIT: ho trovato uno strumento / plugin gratuito ancora migliore chiamato ApexSQL ... http://www.apexsql.com/


11

Opinione personale: usali solo dove sono richiesti. (Vedi la risposta di TheTXI sopra per l'elenco richiesto.)

Dal momento che il compilatore non li richiede, è possibile metterli dappertutto, ma perché? Il compilatore non ti dirà dove l'hai dimenticato, quindi finirai con un uso incoerente.

[Questa opinione è specifica per SQL Server. Altri database potrebbero avere requisiti più rigorosi. Se si sta scrivendo SQL per l'esecuzione su più database, i requisiti possono variare.]

tpdi ha affermato sopra, "in uno script, poiché stai inviando più di un'istruzione, ne hai bisogno". In realtà non è corretto. Non hai bisogno di loro.

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

Produzione:

Semicolons are optional
Semicolons are optional
Semicolons are optional
Semicolons are optional

1
Cosa ne pensi di questa discussione? sqlservercentral.com/Forums/Topic636549-8-1.aspx (puoi usare bugmenot@bugmenot.com: bugmenot se non disponi di un account)
Anwar Pinto

2
Apprezzo che tu abbia affermato chiaramente che questa è solo la tua opinione, tuttavia non credo che dia una buona risposta perché è in conflitto con la documentazione Microsoft e lo standard ANSI. Penso che questa opinione sarebbe migliore in un commento. (Non tentando di colpire te, hai totalmente diritto alle tue opinioni sull'uso dei punti e virgola!)
Iizzy

4

Ho ancora molto da imparare su T-SQL, ma lavorando su un codice per una transazione (e basando il codice su esempi da StackOverflow e altri siti) ho trovato un caso in cui sembra che sia richiesto un punto e virgola e se manca, l'affermazione non sembra affatto essere eseguita e non viene generato alcun errore. Questo non sembra essere coperto in nessuna delle risposte di cui sopra. (Questo utilizzava MS SQL Server 2012.)

Una volta che la transazione ha funzionato nel modo desiderato, ho deciso di provare a cercarla in modo che, in caso di errori, venga ripristinata. Solo dopo aver fatto ciò, la transazione non è stata impegnata (SSMS lo conferma quando si tenta di chiudere la finestra con un bel messaggio che avvisa che esiste una transazione non impegnata.

Così questo

COMMIT TRANSACTION 

all'esterno di un blocco BEGIN TRY / END TRY ha funzionato correttamente per eseguire il commit della transazione, ma all'interno del blocco doveva essere

COMMIT TRANSACTION;

Si noti che non viene fornito alcun errore o avviso e nessuna indicazione che la transazione sia ancora non impegnata fino al tentativo di chiudere la scheda della query.

Fortunatamente questo causa un problema così grande che è immediatamente ovvio che esiste un problema. Sfortunatamente, poiché non viene segnalato alcun errore (sintassi o altro), non è stato immediatamente evidente quale fosse il problema.

Contrariamente, ROLLBACK TRANSACTION sembra funzionare altrettanto bene nel blocco BEGIN CATCH con o senza punto e virgola.

Potrebbe esserci qualche logica in questo, ma sembra arbitrario e Alice nel Paese delle Meraviglie.


Una possibile causa di ciò è che COMMIT TRANSACTIONaccetta una transazione facoltativa / nome del punto di salvataggio (che ignorerà). Senza un punto e virgola terminante, COMMIT TRANSACTIONpuò utilizzare il simbolo successivo se analizza come identificatore, che può cambiare radicalmente la semantica del codice. Se ciò si traduce in un errore, CATCHpotrebbe attivarsi senza che sia COMMITmai stato eseguito. Al contrario, pur ROLLBACK TRANSACTIONaccettando anche un identificatore facoltativo come questo, un errore nell'analisi è molto probabile che comporti il ​​rollback della transazione comunque.
Jeroen Mostert,

3

Sembra che virgola non dovrebbero essere usati in combinazione con operazioni di cursore: OPEN, FETCH, CLOSEe DEALLOCATE. Ho appena perso un paio d'ore con questo. Ho dato uno sguardo da vicino al BOL e ho notato che [;] non è mostrato nella sintassi per queste istruzioni del cursore !!

Quindi ho avuto:

OPEN mycursor;

e questo mi ha dato l'errore 16916.

Ma:

OPEN mycursor

lavorato.


2
Non penso sia corretto. Il BOL non è molto coerente nel menzionare il punto e virgola sulla sintassi dell'istruzione, per esempio, dai un'occhiata a SELECT. Inoltre ho assistito ad OPEN someCursor; funziona bene, lo stesso vale per FETCH, CLOSE e DEALLOCATE ...
Valentino Vranken,

Questo mi suggerisce un bug con il parser. Quale versione di SQL Server stai / stavi usando?
Stewart


0

Quando si utilizza un'istruzione DISABLE o ENABLE TRIGGER in un batch che contiene altre istruzioni, l'istruzione appena prima deve terminare con un punto e virgola. Altrimenti, otterrai un errore di sintassi. Mi sono strappato i capelli con questo ... E dopo, sono incappato in questo oggetto MS Connect per la stessa cosa. È chiuso perché non risolverà.

vedi qui


0

Nota: questo risponde alla domanda come scritto, ma non al problema come indicato. Aggiungendolo qui, poiché la gente lo cercherà

Il punto e virgola viene anche usato prima WITHnelle dichiarazioni CTE ricorsive:

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

Questa query genererà un CTE chiamato Numbers che consiste in numeri interi [1..10]. Per farlo, crea una tabella con solo il valore 1, quindi ricorri fino a raggiungere 10.


8
Tecnicamente non "prima con", ma dopo tutto ciò che viene prima. Se with è la prima istruzione nel batch, non è richiesto il punto e virgola.
Tor Haugen,

Non viene utilizzato anche prima di WITH. Questo è solo il punto e virgola che termina la precedente istruzione. Sembra che alcune persone abbiano deciso che il punto e virgola dovrebbe essere qui, poiché si tratta di uno scenario in cui è richiesto il punto e virgola. Perché queste persone hanno deciso che questo è superiore alle dichiarazioni sempre terminanti con punto e virgola, non ne ho idea.
Stewart,

0

Se ti piace ottenere errori casuali di Timeout dei comandi in SQL Server, lascia i punti e virgola alla fine delle stringhe CommandText.

Non so se questo sia documentato da nessuna parte o se sia un bug, ma succede e l'ho imparato da amara esperienza.

Ho esempi verificabili e riproducibili utilizzando SQLServer 2008.

aka -> In pratica, includere sempre il terminatore anche se si sta semplicemente inviando un'istruzione al database.


Se stai ottenendo timeout per una query basata su nient'altro che sulla fine del punto e virgola o meno, ciò è quasi certamente causato da piani di esecuzione diversi, poiché questi vengono memorizzati nella cache facendo corrispondere il testo esatto della query, incluso altrimenti semanticamente irrilevante cose come spazi bianchi, commenti e un punto e virgola terminante. Il punto e virgola stesso sarà del tutto innocente nel causare eventuali problemi di temporizzazione.
Jeroen Mostert,

-2

I punti e virgola non funzionano sempre nelle istruzioni SELECT composte.

Confronta queste due diverse versioni di una banale istruzione SELECT composta.

Il codice

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

ritorna

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

Tuttavia, il codice

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

ritorna

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

(1 row(s) affected)

11
[Un anno dopo]: Wow, sono sorpreso che nessuno abbia ancora commentato questa risposta! Ovviamente non funzionerà, i punti e virgola sono separatori di istruzioni, quindi il tuo codice con i punti e virgola è: 1- SELECT @ Test = (SELECT (SELECT (SELECT (SELECT (i punti e virgola non funzionano sempre bene); - questo non è corretto istruzione 2-); - neanche questo 3-); - né quello 4-); - neanche quello il punto e virgola dovrebbe essere dopo la 3 parentesi
PhpLou

1
Si utilizzano solo punti e virgola per terminare le istruzioni . Una sottoquery non è un'affermazione. Le dichiarazioni sono cose che vengono eseguite in sequenza. Nel tuo esempio, ci sono tre affermazioni: 1. DECLARE @ Test varchar (35) 2. SELECT @ Test = (SELECT (SELECT (SELECT (SELECT 'I punti e virgola non sempre funzionano bene.'))) 3. SELECT @ Test Test
Stewart
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.