Use of Begin / End Blocks and the Go keyword in SQL Server?
What are the guidelines as to when to use begin
and end
blocks in SQL Server?
Also, what exactly does the Go
keyword do?
Solution 1:
GO is like the end of a script.
You could have multiple CREATE TABLE statements, separated by GO. It's a way of isolating one part of the script from another, but submitting it all in one block.
BEGIN and END are just like { and } in C/++/#, Java, etc.
They bound a logical block of code. I tend to use BEGIN and END at the start and end of a stored procedure, but it's not strictly necessary there. Where it IS necessary is for loops, and IF statements, etc, where you need more then one step...
IF EXISTS (SELECT * FROM my_table WHERE id = @id)
BEGIN
INSERT INTO Log SELECT @id, 'deleted'
DELETE my_table WHERE id = @id
END
Solution 2:
You need BEGIN ... END to create a block spanning more than one statement. So, if you wanted to do 2 things in one 'leg' of an IF statement, or if you wanted to do more than one thing in the body of a WHILE loop, you'd need to bracket those statements with BEGIN...END.
The GO keyword is not part of SQL. It's only used by Query Analyzer to divide scripts into "batches" that are executed independently.
Solution 3:
GO isn't a keyword in SQL Server; it's a batch separator. GO ends a batch of statements. This is especially useful when you are using something like SQLCMD. Imagine you are entering in SQL statements on the command line. You don't necessarily want the thing to execute every time you end a statement, so SQL Server does nothing until you enter "GO".
Likewise, before your batch starts, you often need to have some objects visible. For example, let's say you are creating a database and then querying it. You can't write:
CREATE DATABASE foo;
USE foo;
CREATE TABLE bar;
because foo does not exist for the batch which does the CREATE TABLE. You'd need to do this:
CREATE DATABASE foo;
GO
USE foo;
CREATE TABLE bar;
Solution 4:
BEGIN and END have been well answered by others.
As Gary points out, GO is a batch separator, used by most of the Microsoft supplied client tools, such as isql, sqlcmd, query analyzer and SQL Server Management studio. (At least some of the tools allow the batch separator to be changed. I have never seen a use for changing the batch separator.)
To answer the question of when to use GO, one needs to know when the SQL must be separated into batches.
Some statements must be the first statement of a batch.
select 1
create procedure #Zero as
return 0
On SQL Server 2000 the error is:
Msg 111, Level 15, State 1, Line 3
'CREATE PROCEDURE' must be the first statement in a query batch.
Msg 178, Level 15, State 1, Line 4
A RETURN statement with a return value cannot be used in this context.
On SQL Server 2005 the error is less helpful:
Msg 178, Level 15, State 1, Procedure #Zero, Line 5
A RETURN statement with a return value cannot be used in this context.
So, use GO
to separate statements that have to be the start of a batch from the statements that precede it in a script.
When running a script, many errors will cause execution of the batch to stop, but then the client will simply send the next batch, execution of the script will not stop. I often use this in testing. I will start the script with begin transaction and end with rollback, doing all the testing in the middle:
begin transaction
go
... test code here ...
go
rollback transaction
That way I always return to the starting state, even if an error happened in the test code, the begin and rollback transaction statements being part of a separate batches still happens. If they weren't in separate batches, then a syntax error would keep begin transaction from happening, since a batch is parsed as a unit. And a runtime error would keep the rollback from happening.
Also, if you are doing an install script, and have several batches in one file, an error in one batch will not keep the script from continuing to run, which may leave a mess. (Always backup before installing.)
Related to what Dave Markel pointed out, there are cases when parsing will fail because SQL Server is looking in the data dictionary for objects that are created earlier in the batch, but parsing can happen before any statements are run. Sometimes this is an issue, sometimes not. I can't come up with a good example. But if you ever get an 'X does not exist' error, when it plainly will exist by that statement break into batches.
And a final note. Transaction can span batches. (See above.) Variables do not span batches.
declare @i int
set @i = 0
go
print @i
Msg 137, Level 15, State 2, Line 1
Must declare the scalar variable "@i".