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?
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?
Risposte:
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.
THROW
una 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
MERGE
anche per esempio). Come menzionato in altre risposte, nello standard ANSI sono richiesti
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.
In SQL2008 BOL affermano che nelle prossime versioni saranno richiesti i punti e virgola. Pertanto, usalo sempre.
Riferimento:
È 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
BEGIN TRY
BEGIN TRAN
SELECT 1/0 AS CauseAnException;
COMMIT
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE();
THROW
END CATCH
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 :-)
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.
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/
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
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.
COMMIT TRANSACTION
accetta una transazione facoltativa / nome del punto di salvataggio (che ignorerà). Senza un punto e virgola terminante, COMMIT TRANSACTION
può utilizzare il simbolo successivo se analizza come identificatore, che può cambiare radicalmente la semantica del codice. Se ciò si traduce in un errore, CATCH
potrebbe attivarsi senza che sia COMMIT
mai stato eseguito. Al contrario, pur ROLLBACK TRANSACTION
accettando anche un identificatore facoltativo come questo, un errore nell'analisi è molto probabile che comporti il rollback della transazione comunque.
Sembra che virgola non dovrebbero essere usati in combinazione con operazioni di cursore: OPEN
, FETCH
, CLOSE
e 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.
Secondo le Convenzioni sulla sintassi Transact-SQL (Transact-SQL) (MSDN)
Terminatore di istruzioni 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.
(vedi anche il commento di @gerryLowry)
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
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 WITH
nelle 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.
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.
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)