Reglas de formato SQL – Terminando sentencias SQL con puntos y comas

Este artículo explica el uso de puntos y comas para terminar sentencias SQL, las diferencias entre el comando GO y el punto y coma.

Terminar sentencias SQL con puntos y comas era opcional en SQL Server 2000 y en algunos casos realmente no estaba permitido. En SQL Server 2005, la introducción de Expresiones de Tabla Comunes (CTEs) e Instrucciones de Service Broker trajeron nuevas reglas de formato. Terminar una sentencia que precedió a las Instrucciones Service Broker (SEND, RECEIVE, BEGIN DIALOG CONVERSATION, y BEGIN CONVERSATION TIMER) y los CTEs (con la sentencia WITH) se vuelve mandatorio si aquellas sentencias no eran las primeras en el lote. Por ejemplo, correr la siguiente consulta donde la sentencia WITH no es la primera en el lote resultará en un error de sintaxis de T-SQL:

INSERT INTO Emails VALUES (1, 'M', 'S')
INSERT INTO Emails VALUES (3, 'R', NULL)
WITH Ms
    AS ( SELECT FirstName ,
                LastName
           FROM Emails
          WHERE LastName = NULL )
    SELECT *
      FROM Ms;

Msg 319, Level 15, State 1, Line 3
Incorrect syntax near the keyword ‘with’. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.

Terminar la sentencia antes de la palabra clave WITH con un punto y coma permitirá ejecutar sin errores:

;WITH Ms AS (...) ...

SQL Server 2008 introdujo una nueva regla para terminar la sentencia MERGE con un punto y coma. No terminar la siguiente sentencia MERGE también resulta con un error de sintaxis:

MERGE INTO Person.Person AS P
USING Person.EmailAddress AS EA
ON P.BusinessEntityID = EA.BusinessEntityID
WHEN MATCHED THEN
UPDATE SET ModifiedDate = EA.ModifiedDate

Msg 10713, Level 15, State 1, Line 5
A MERGE statement must be terminated by a semi-colon (;).

En SQL Server 2012 la sentencia THROW fue introducida con la misma regla para terminar la sentencia SQL como la sentencia WITH. Si la sentencia THROW no es la primera sentencia en el bloque CATCH, la sentencia que la precede debe ser terminada con un punto y coma. Ejecutar la siguiente consulta…

BEGIN TRY
INSERT INTO Person.ContactType( Name, ModifiedDate)
VALUES( 'nj', null);
END TRY
BEGIN CATCH
IF ERROR_NUMBER() = 515
BEGIN
PRINT 'NULL violation';
END
BEGIN
PRINT 'Re-throw'
THROW; 
END
END CATCH;

Resulta con un error de sintaxis porque el commando PRINT ‘Re-throw’ no es terminado con un punto y coma:

Msg 102, Level 15, State 1, Line 12
Incorrect syntax near ‘THROW’.

No terminar las sentencias con un punto y coma es también una característica deprecada en SQL Server 2012.

Note que el uso del punto y coma para terminar sentencias difiere del comando GO.

Las Interfaces de Programación de Aplicaciones (APIs) como ADO.NET le proveen con métodos para enviar un lote de código a SQL Server para ejecutar. Las utilidades de SQL Server como SQL Server Management Studio, SQLCMD y OSQL provee un comando de cliente llamado GO que señala el final de un lote. Note que el comando GO es un comando de cliente y no un comando de servidor T-SQL [1].

Terminar sentencias SQL con el comando GO parecerá válido algunas veces como en el ejemplo siguiente, donde el comando GO señala el fin de un lote y la consulta se ejecuta sin errores porque la sentencia WITH es ahora primera en el lote. Pero esto no termina la sentencia antes de la sentencia WITH apropiadamente:

INSERT INTO Emails VALUES (1, 'M', 'S')
INSERT INTO Emails VALUES (3, 'R', NULL)
GO
WITH Ms
    AS ( SELECT FirstName ,
                LastName
           FROM Emails
          WHERE LastName = NULL )
    SELECT *
      FROM Ms;

Usando ApexSQL Refactor, usted puede terminar todas las sentencias SQL con un punto y coma para prevenir errores de sintaxis en versiones futuras de SQL Server y formatear el código SQL y los scripts para cumplir con las reglas de formato SQL.

EN el menú de ApexSQL Refactor, elija el comando Options y abra el diálogo Options. En la pestaña Formatting seleccione la opción Always use statement terminator:

Selecting the Always use statement terminator feature in ApexSQL Refactor

INSERT INTO Emails VALUES (1, 'M', 'S')
INSERT INTO Emails VALUES (3, 'R', NULL)
WITH Ms
    AS ( SELECT FirstName ,
                LastName
           FROM Emails
          WHERE LastName = NULL )
    SELECT *
      FROM Ms

Esta opción terminará todas las sentencias en el código anterior con un punto y coma:

INSERT INTO Emails VALUES (1, 'M', 'S');
INSERT INTO Emails VALUES (3, 'R', NULL);
WITH Ms
    AS ( SELECT FirstName ,
                LastName
           FROM Emails
          WHERE LastName = NULL )
    SELECT *
      FROM Ms;

Referencias
[1] Microsoft® SQL Server ® 2012 T-SQL Fundamentals – Itzik Ben-Gan

Recursos útiles:
Books Online for SQL Server – THROW (Transact-SQL)
Books Online for SQL Server – WITH common_table_expression (Transact-SQL)
Books Online for SQL Server – GO (Transact SQL)
Books Online for SQL Server – Deprecated Database Engine Features in SQL Server 2012

Traductor: Daniel Calbimonte

octubre 16, 2016