]]>By: thomasrushtonhttp://blog.sqlauthority.com/2011/12/09/sql-server-bad-practice-of-using-keywords-as-an-object-name-avoid-using-keywords-as-an-object/#comment-214161
Fri, 09 Dec 2011 18:05:17 +0000http://blog.sqlauthority.com/?p=16261#comment-214161You can change the batch delimiter used by SSMS from “GO” to “xyzzy”, or “8”, or pretty much anything you want. Jonathan @fatherjack Allen did a demo at SQLBits recently showing some of the weirdness that can happen if you set it to a number…

]]>By: DHallhttp://blog.sqlauthority.com/2011/12/09/sql-server-bad-practice-of-using-keywords-as-an-object-name-avoid-using-keywords-as-an-object/#comment-213797
Fri, 09 Dec 2011 03:29:56 +0000http://blog.sqlauthority.com/?p=16261#comment-213797The second point you make isn’t exactly accurate. The semicolon has nothing (or very little) to do with executing the GO stored procedure. The code works the same even without the semicolon as long as EXEC and GO are on the same line or if [GO] is wrapped in square brackets.

However, if the GO proc name is the only thing (other than an optional comment) on the line following following the EXEC command, then the SQL query window will try to interpret it as a batch delimiter if it’s not followed by a semicolon or wrapped in square braces.

In other words, the following SQL will work as expected

INSERT INTO T1(ID) exec GO — Note no semicolon
SELECT * FROM T1

— and so will this:
INSERT INTO T1(ID) exec
GO; — Note the semicolon
SELECT * FROM T1

— and so will this:
INSERT INTO T1(ID) exec
[GO] — Note the square brackets but no semicolon
SELECT * FROM T1

— but this won’t:

INSERT INTO T1(ID) exec
GO — Note no semicolon
SELECT * FROM T1

Another evidence that GO is different from SQL reserved word is to duplicate your experiment using [TABLE] as the proc name instead of GO. You’ll note that unlike the word GO, the word TABLE must be wrapped in square brackets so that TSQL will allow it to be an object name. For GO, the square brackets are optional.

— The following code works fine
CREATE PROCEDURE [TABLE]
AS SELECT 1 AS NUMBER
GO
INSERT INTO T1(ID) exec [TABLE] — Note the square brackets
SELECT * FROM T1

— but this generates a syntax error
CREATE PROCEDURE [TABLE]
AS SELECT 1 AS NUMBER
GO
INSERT INTO T1(ID) exec TABLE — Note no square brackets
SELECT * FROM T1

As you mention in your first point, using keywords in this manner can be trouble, and should generally be avoided for many reasons, but it especially helps in this case to understand that GO is not a reserved word in TSQL, but only in some of the tools (like SSMS) that process SQL queries in batches.

The following excerpt from SQL BOL should help clarify the difference between the GO batch delimiter and true SQL reserved words.

GO is not a Transact-SQL statement; it is a command recognized by the sqlcmd and osql utilities and SQL Server Management Studio Code editor.

SQL Server utilities interpret GO as a signal that they should send the current batch of Transact-SQL statements to an instance of SQL Server. The current batch of statements is composed of all statements entered since the last GO, or since the start of the ad hoc session or script if this is the first GO.

A Transact-SQL statement cannot occupy the same line as a GO command. However, the line can contain comments.