Por que uma CTE deve começar com ponto e vírgula?

13

Eu estava apenas olhando para um post no StackOverflow, em que Aaron Bertrand propõe o uso de uma CTE em vez de uma tabela de números, que é uma maneira elegante de executar a tarefa em questão. Minha pergunta é: por que a primeira linha do CTE começa com um ponto e vírgula?

;WITH n AS (SELECT TOP (10000) n FROM 
  (SELECT n = ROW_NUMBER() OVER
    (ORDER BY s1.[object_id])
    FROM sys.all_objects AS s1
    CROSS JOIN sys.all_objects AS s2
  ) AS x ORDER BY n
)
SELECT n FROM n ORDER BY n; -- look ma, no gaps!

Isso é para garantir que a instrução WITH não seja analisada em SELECTalgo anterior ou algo assim? Não vejo nada no BOL do SQL Server 2005 sobre o uso de ponto e vírgula antes do WITH.

Max Vernon
fonte

Respostas:

25

Eu sempre faço isso ao postar aqui ou no StackOverflow porque, WITHporque a palavra-chave está sobrecarregada, o comando anterior requer um ponto e vírgula final. Se eu colar um exemplo de código que usa um CTE, inevitavelmente algum usuário o colará no código existente, e a instrução anterior não terá ponto e vírgula. Portanto, o código quebra e recebo reclamações como:

Seu código quebrou! Recebi esta mensagem de erro:

Incorrect syntax near 'WITH'...

Embora eu queira acreditar que as pessoas estão se tornando melhores em sempre encerrar suas declarações com ponto e vírgula , prefiro evitar o ruído e incluí-lo sempre. Algumas pessoas não gostam, mas <shrug />. Você pode incluir o ponto e vírgula antes ou depois de uma declaração válida, conforme desejar. Isso é válido:

;;;;SELECT 1;;;;;;;;;;;;SELECT 2;;;;;;;;SELECT 3;;;;;

Portanto, não há mal em haver um ponto e vírgula extra antes de uma declaração que, por definição, exige isso. É mais seguro fazê-lo, mesmo que não seja tão bonito.

Ele precisa ser redigido de maneira estranha para entender o ponto, mas "não encerrar uma declaração válida com ponto e vírgula" está realmente obsoleto desde o SQL Server 2008. Portanto, como descrevi na postagem do blog, vinculo acima, mesmo nos casos em que não é necessário ignorar um erro, ele deve ser usado sempre que válido. Você pode ver isso aqui:

http://msdn.microsoft.com/en-us/library/ms143729.aspx

(Pesquise a última página por "ponto e vírgula")

Claro que não seria o SQL Server se não houvesse exceções. Tente o seguinte:

BEGIN TRY;
  SELECT 1/1;
END TRY;
BEGIN CATCH;
  SELECT 1/1;
END CATCH;

Não é a única exceção à regra, mas é a que acho mais pouco intuitiva.

Aaron Bertrand
fonte
1
Em 2012, até recebo a mesma mensagem de erro, mas apenas por causa do ponto e vírgula após END TRY: i.stack.imgur.com/rc6dw.png - se eu remover esse ponto e vírgula, tudo funcionará.
Aaron Bertrand
Eu acho que você não pode colocar um ponto-e-vírgula antes, BEGIN CATCHsimplesmente porque faz parte de uma única declaração composta apresentada com BEGIN TRY. É o mesmo que colocar um ponto e vírgula antes da IFdeclaração ELSE.
Andriy M
@AndriyM Fui informado de uma conversa muito mais detalhada sobre as regras aqui. Eu mencionei isso porque é uma surpresa para todos que o conhecem, não porque eu não entendo o motivo. :-)
Aaron Bertrand
10

Isso é para garantir que ele não esteja incluído em nenhuma instrução anterior, pois WITHpode servir a vários propósitos no T-SQL.

Se é a primeira declaração do lote, não acho que você precise.

swasheck
fonte