Quando devo usar ponto e vírgula no SQL Server?

221

Ao verificar algum código na web e scripts gerados pelo SQL Server Management Studio, observei que algumas instruções terminam com ponto e vírgula.

Então, quando devo usá-lo?

Anwar Pinto
fonte
23
SQL Server 2008 R2 msdn.microsoft.com/en-us/library/ms177563.aspx "Convenções de sintaxe do Transact-SQL (Transact-SQL)" ; == Terminador de instrução Transact-SQL. Embora o ponto-e-vírgula não seja necessário para a maioria das instruções nesta versão do SQL Server, será necessário em uma versão futura .
usar o seguinte código
2
Embora eles afirmem que um ponto e vírgula será necessário em uma versão futura, isso nunca se tornará realidade. Eles nunca podem exigir isso por razões de compatibilidade. Quebraria cerca de 100% dos aplicativos.
usr
1
Agora é 2019 e nenhum ponto e vírgula ainda é aceito com prazer na versão mais recente do SQL Server. Como o @usr diz, a menos que a Microsoft queira fazer uma pausa 100% limpa, não há como eles aplicarem isso.
Ian Kemp

Respostas:

152

De um artigo do SQLServerCentral.Com de Ken Powers:

O ponto e vírgula

O caractere ponto-e-vírgula é um terminador de instrução. Faz parte do padrão ANSI SQL-92, mas nunca foi usado no Transact-SQL. De fato, foi possível codificar o T-SQL por anos sem encontrar um ponto e vírgula.

Uso

Há duas situações nas quais você deve usar o ponto e vírgula. A primeira situação é onde você usa uma CTE (Common Table Expression) e a CTE não é a primeira instrução do lote. A segunda é onde você emite uma declaração do Service Broker e a declaração do Service Broker não é a primeira no lote.

TheTXI
fonte
9
É THROWuma declaração do Service Broker? Precisamos incluir um ponto-e-vírgula antes de um lançamento neste exemplo:BEGIN ;THROW @Error, 'Invalid FundingID', 2; RETURN END
Chris Walsh
1
Parece que eles estão incentivando basicamente o uso do ponto e vírgula em geral, exigindo-o antes de todos os novos tipos de instrução que foram introduzidos nos últimos anos. ( MERGEtambém por exemplo). Como mencionado em outras respostas, no padrão ANSI eles são obrigados
Mark Sowul
2
@maococam Acho que você leu o documento incorretamente. Se você olhar para esse link, ele diz " Não finalizando instruções Transact-SQL com ponto e vírgula". está obsoleto.
Caltor
A meu ver, isso realmente não aborda a questão de quando alguém deve (em oposição a deve ) usar um ponto e vírgula.
Stewart
81

Por padrão, as instruções SQL são finalizadas com ponto e vírgula. Você usa um ponto-e-vírgula para encerrar instruções, a menos que (raramente) tenha definido um novo terminador de instruções.

Se você estiver enviando apenas uma declaração, tecnicamente poderá dispensar o terminador da declaração; em um script, como você está enviando mais de uma declaração, é necessário.

Na prática, sempre inclua o terminador, mesmo se você estiver apenas enviando uma instrução para o banco de dados.

Editar: em resposta àqueles que dizem que os terminadores de instruções não são exigidos por [RDBMS específico], embora isso possa ser verdade, eles são exigidos pelo ANSI SQL Standard. Em toda a programação, se podemos aderir a um padrão sem perda de funcionalidade, devemos fazê-lo, porque nem nosso código nem nossos hábitos estão vinculados a um fornecedor proprietário.

Com alguns compiladores C, é possível que o retorno principal seja nulo, mesmo que o Standard exija que main retorne int. Mas fazer isso torna nosso código e nós mesmos menos portáteis.

A maior dificuldade em programar efetivamente não é aprender coisas novas, é desaprender maus hábitos. Na medida em que podemos evitar adquirir maus hábitos em primeiro lugar, é uma vitória para nós, para nosso código e para qualquer pessoa que esteja lendo ou usando nosso código.

tpdi
fonte
25

Você deve usá-lo.

A prática de usar um ponto-e-vírgula para finalizar instruções é padrão e, de fato, é um requisito em várias outras plataformas de banco de dados. O SQL Server requer o ponto e vírgula apenas em casos específicos - mas nos casos em que não é necessário um ponto e vírgula, o uso de um não causa problemas. Eu recomendo fortemente que você adote a prática de encerrar todas as declarações com ponto e vírgula. Isso não apenas melhora a legibilidade do seu código, mas, em alguns casos, pode poupar algum sofrimento. (Quando um ponto-e-vírgula é necessário e não é especificado, a mensagem de erro que o SQL Server produz nem sempre é muito clara.)

E o mais importante:

A documentação do SQL Server indica que não encerrar instruções T-SQL com ponto-e-vírgula é um recurso obsoleto. Isso significa que o objetivo a longo prazo é impor o uso do ponto e vírgula em uma versão futura do produto. Essa é mais uma razão para adquirir o hábito de encerrar todas as suas declarações, mesmo onde atualmente não é necessário.

Fonte: Fundamentos de T-SQL do Microsoft SQL Server 2012 por Itzik Ben-Gan.


Um exemplo de por que você sempre deve usar ;são as duas consultas a seguir (copiadas desta postagem ):

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

insira a descrição da imagem aqui

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

insira a descrição da imagem aqui

gotqn
fonte
7
Este parece ser um forte argumento que você deve usar ponto e vírgula (apoiados por as aspas), mas apenas um único caso em que há uma obrigação .
Gregor Thomas
3
@ Gregor, se for anunciado que o uso de ponto e vírgula é uma not using themtécnica obrigatória e obsoleta, você deve usá-los. Caso contrário, existe o risco de sofrer no futuro. Se você não estiver planejando atualizar / trabalho interruptor e sempre vai trabalhar com SQL Server 2000 você está seguro :-)
gotqn
5
Certo, deveria , eu concordo. Mas ele primeira linha de você resposta enfatiza obrigação , o que não é o caso --- pelo menos não ainda.
Gregor Thomas
2
O exemplo com ponto e vírgula resulta no Incorrect syntax near 'THROW'.SQL Server 2008 (10.0.6241.0), que é a versão com a qual tenho de lidar no trabalho. Funciona como mostrado em 2012. Fui convencido a começar a usar ponto e vírgula por causa da descontinuação. Não espero que seja um problema em 2008 na maioria das vezes.
Pilot_51
1
Sua resposta é a melhor de longe! Merece muito mais votos.
Stewart
22

Se eu ler isso corretamente, será necessário usar ponto-e-vírgula para finalizar as instruções TSQL. http://msdn.microsoft.com/en-us/library/ms143729%28v=sql.120%29.aspx

EDIT: Encontrei um plug-in para o SSMS 2008R2 que irá formatar seu script e adicionar os pontos e vírgulas. Eu acho que ainda está na versão beta ...

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

EDIT: Encontrei uma ferramenta / plugin grátis ainda melhor chamada ApexSQL ... http://www.apexsql.com/

Spidermain50
fonte
11

Opinião pessoal: use-os somente onde for necessário. (Veja a resposta do TheTXI acima para a lista necessária.)

Como o compilador não exige, você pode colocá-los por toda parte, mas por quê? O compilador não lhe dirá onde você esqueceu um, então você terminará com um uso inconsistente.

[Esta opinião é específica para o SQL Server. Outros bancos de dados podem ter requisitos mais rigorosos. Se você estiver escrevendo o SQL para executar em vários bancos de dados, seus requisitos poderão variar.]

tpdi afirmou acima, "em um script, como você está enviando mais de uma declaração, você precisa dela". Na verdade, isso não está correto. Você não precisa deles.

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

Resultado:

Semicolons are optional
Semicolons are optional
Semicolons are optional
Semicolons are optional
Rob Garrison
fonte
1
O que você acha dessa discussão? sqlservercentral.com/Forums/Topic636549-8-1.aspx (Yoy pode usar [email protected]: bugmenot se você não tiver uma conta)
Anwar Pinto
2
Compreendo que você tenha declarado claramente que essa é apenas a sua opinião, no entanto, não acho que seja uma boa resposta, pois entra em conflito com a documentação da Microsoft e o padrão ANSI. Eu acho que essa opinião seria melhor em um comentário. (Não tentar bater-lhe, você está totalmente direito a suas opiniões sobre o uso de ponto e vírgula!)
Izzy
4

Ainda tenho muito a aprender sobre o T-SQL, mas, ao elaborar algum código para uma transação (e basear o código em exemplos de stackoverflow e outros sites), encontrei um caso em que parece que é necessário um ponto-e-vírgula e, se estiver faltando, a instrução parece não ser executada e nenhum erro é gerado. Isso não parece ser coberto em nenhuma das respostas acima. (Isso estava usando o MS SQL Server 2012.)

Depois que a transação funcionou da maneira que eu queria, decidi colocar um try-catch em volta, para que, se houver algum erro, ela seja revertida. Somente depois de fazer isso, a transação não foi confirmada (o SSMS confirma isso ao tentar fechar a janela com uma boa mensagem alertando você para o fato de que há uma transação não confirmada.

Então, é isso

COMMIT TRANSACTION 

fora de um bloco BEGIN TRY / END TRY funcionou bem para confirmar a transação, mas dentro do bloco tinha que ser

COMMIT TRANSACTION;

Observe que não há erro ou aviso fornecido e nenhuma indicação de que a transação ainda não foi confirmada até tentar fechar a guia de consulta.

Felizmente, isso causa um problema tão grande que é imediatamente óbvio que existe um problema. Infelizmente, como nenhum erro (sintaxe ou não) é relatado, não ficou imediatamente claro qual era o problema.

Por outro lado, ROLLBACK TRANSACTION parece funcionar igualmente bem no bloco BEGIN CATCH com ou sem ponto e vírgula.

Pode haver alguma lógica para isso, mas parece arbitrário e Alice no País das Maravilhas.

Matthew Davidian
fonte
Uma causa possível disso é que COMMIT TRANSACTIONaceita um nome opcional de transação / ponto de salvamento (que ele ignorará). Sem um ponto-e-vírgula final, COMMIT TRANSACTIONpode comer o próximo símbolo se analisar como um identificador, o que pode mudar radicalmente a semântica do código. Se isso resultar em um erro, o CATCHgatilho pode ser disparado sem que COMMITele tenha sido executado. Por outro lado, embora ROLLBACK TRANSACTIONtambém aceite um identificador opcional como este, um erro na análise de lá provavelmente resultará na reversão da transação de qualquer maneira.
Jeroen Mostert
3

Parece que ponto e vírgula não deve ser usado em conjunto com operações de cursor: OPEN, FETCH, CLOSEeDEALLOCATE . Só perdi algumas horas com isso. Eu examinei atentamente o BOL e notei que [;] não é mostrado na sintaxe para essas instruções do cursor !!

Então eu tive:

OPEN mycursor;

e isso me deu o erro 16916.

Mas:

OPEN mycursor

trabalhou.

rab
fonte
2
Eu não acho que isso esteja correto. O BOL não é muito consistente ao mencionar o ponto-e-vírgula na sintaxe da instrução. Dê uma olhada no SELECT, por exemplo. Além disso, eu testemunhei OPEN someCursor; funcionando bem, o mesmo para buscar, fechar e des ...
Valentino Vranken
Isso me sugere um erro no analisador. Qual versão do SQL Server você está usando?
Stewart
2

De acordo com as convenções de sintaxe Transact-SQL (Transact-SQL) (MSDN)

Terminador de instruções Transact-SQL. Embora o ponto-e-vírgula não seja necessário para a maioria das instruções nesta versão do SQL Server, será necessário em uma versão futura.

(veja também o comentário de @gerryLowry)

Alan B
fonte
0

Ao usar uma instrução DISABLE ou ENABLE TRIGGER em um lote que contenha outras instruções, a instrução imediatamente antes de terminar com ponto e vírgula. Caso contrário, você receberá um erro de sintaxe. Eu arranquei meu cabelo com este ... E depois, tropecei neste item do MS Connect sobre a mesma coisa. Está fechado como não será corrigido.

veja aqui

Nick V
fonte
0

Nota: Isso responde à pergunta como está escrita, mas não ao problema como indicado. Adicionando aqui, pois as pessoas o procurarão

O ponto-e-vírgula também é usado antes WITHem declarações CTE recursivas:

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

Esta consulta irá gerar um CTE chamado Numbers, que consiste em números inteiros [1..10]. Isso é feito criando uma tabela apenas com o valor 1 e recorrendo até atingir 10.

v010dya
fonte
8
Tecnicamente, não 'antes com', mas depois do que vier antes com. Se with for a primeira instrução do lote, não será necessário ponto e vírgula.
precisa saber é o seguinte
Não é também usado antes COM. Este é apenas o ponto e vírgula que encerra a instrução anterior. Parece que algumas pessoas decidiram que o ponto e vírgula deveria estar aqui, pois esse é um cenário no qual o ponto e vírgula é necessário. Por que essas pessoas decidiram que isso é superior a sempre encerrar declarações com ponto e vírgula, não faço ideia.
Stewart
0

Se você deseja obter erros aleatórios de tempo limite do comando no SQLServer, deixe o ponto e vírgula no final de suas seqüências de caracteres CommandText.

Não sei se isso está documentado em algum lugar ou se é um bug, mas acontece e aprendi isso com uma experiência amarga.

Eu tenho exemplos verificáveis ​​e reproduzíveis usando o SQLServer 2008.

tcp -> Na prática, sempre inclua o terminador, mesmo se você estiver apenas enviando uma instrução para o banco de dados.

Allan Maher
fonte
Se você estiver recebendo tempos limite para uma consulta com base em mais nada, exceto se existe ou não um ponto-e-vírgula no final, isso quase certamente é causado por ter planos de execução diferentes, pois esses são armazenados em cache pela correspondência no texto exato da consulta, incluindo de outra maneira semanticamente irrelevante coisas como espaço em branco, comentários e um ponto e vírgula final. O ponto e vírgula em si será totalmente inocente de causar problemas de tempo.
Jeroen Mostert
-2

Ponto-e-vírgula nem sempre funcionam em instruções SELECT compostas.

Compare essas duas versões diferentes de uma instrução SELECT composta trivial.

O código

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

retorna

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

No entanto, o código

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

retorna

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

(1 row(s) affected)
John Feild
fonte
11
[Um ano depois]: Uau, estou surpreso que ninguém tenha comentado sobre esta resposta ainda! É claro que não vai funcionar, ponto e vírgula são separadores de instruções; portanto, seu código com ponto e vírgula é: 1- SELECT @ Test = (SELECT (SELECT (SELECT ('Ponto e vírgula nem sempre funcionam bem.'; - isso não é correto) declaração 2-); - nem isso é 3-); - nem aquele 4-); --neither que um ponto e vírgula a deve ser depois o 3 parêntesis
PhpLou
1
Você usa apenas ponto-e-vírgula para finalizar instruções . Uma subconsulta não é uma declaração. Instruções são coisas que são executadas em sequência. No seu exemplo, existem três instruções: 1. DECLARE @ Test varchar (35) 2. SELECT @ Test = (SELECT (SELECT (SELECT (SELECT 'Ponto e vírgula nem sempre funcionam bem.')))) 3. SELECT @ Test Test
Stewart