What is the point of having a batch separator?
Having read many of the answers, and contributed to comments, here is what I think.
The real question is "What is the point of having a batch?"
There are 2 implications of batching that have some meaning, and there is an additional usage of go
that can be useful:
1. All statements in a batch are compiled into a single execution plan
How this impacts you, as a SQL developer, I don't know. But there it is. The implication of this is that you can't have some statements within the same batch. For example, you cannot ALTER
a table to add a column, then select
that column in the same batch - because while compiling the execution plan, that column does not exist for selecting.
I think there is an open argument as to whether SQL Server should be able to detect this by itself without requiring developers to include go
statements in their scripts. Further, the docs say ODBC connections may never issue a go
command. It is not clear to me how a script run through ODBC would behave if it included the ALTER
/ SELECT
example just given.
2. Locally declared variables exist only within the scope of the batch in which they were declared
These two points combined kind of suck. I have a script that creates and alters DB structures (tables, procedures, etc) and I want to declare variables at the start of the script that will be used to govern the behaviour of the script overall. As soon as I need to wrap up a batch (due to, say, an ALTER
statement - see my point 1, above), those "config" variables fall out of scope and can't be used further down the script. My workaround is to create a table, persist the config variables into the table, then read from that table all the way through my script, then drop the table at the end (in case anyone else is facing this).
This second implication can actually be used to advantage - if your script is doing a lot of work and you simply want to clear out all your local variables, you can simply include a GO
statement and then declare new variables (ie. and re-use the same names, if that's what you want).
3. GO has an optional parameter (named "count") which tells the server to repeat the batch actions multiple times
This usage seems to be nice additional functionality added on to the GO
statement. I believe the initial or primary function of GO
relates more to the compilation of a single execution plan, as mentioned in point 1 - otherwise the keyword may as well be something like REPEAT 10
- but repeat what? The batch. Without GO
signifying a batch, a repeat command could only ever repeat the prior single statement. Therefore GO
is a nice way to repeat batches.
Reference
All of this comes from trying to understand the MS documentation on GO. Many of the other answers - here, and on other questions - pick at pieces of the documentation but I think the documentation itself fails to really explain why there is a benefit to batching in the first place - hence my contribution to an already well-commented question.
Addendum
After writing the above, I did find the Rules for Using Batches mentioned by Microsoft in the GO
documentation. The linked page explains that an execution plan consists of multiple statements. It also says that individual statements can be re-compiled into a new execution plan (ie by SQL Server, while processing the batch, automatically). So for example, following a statement to CREATE TABLE
you might have an INSERT
into that table. That INSERT
statement will be recompiled after the table has been created in the prior statement.
This re-enforces the idea that SQL Server probably could detect those scenarios where an ALTER
to a table is followed by a SELECT
and that it needs to re-compile the SELECT
(see my point 1 above), and possibly this is exactly what happens if using ODBC (see point 1 above).
None of this new information alters the 3 points given above. The link I just gave contains additional reading and ends with "the rules", which are these:
CREATE DEFAULT, CREATE FUNCTION, CREATE PROCEDURE, CREATE RULE, CREATE SCHEMA, CREATE TRIGGER, and CREATE VIEW statements cannot be combined with other statements in a batch. The CREATE statement must start the batch. All other statements that follow in that batch will be interpreted as part of the definition of the first CREATE statement.
A table cannot be changed and then the new columns referenced in the same batch.
If an EXECUTE statement is the first statement in a batch, the EXECUTE keyword is not required. The EXECUTE keyword is required if the EXECUTE statement is not the first statement in the batch.