Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2008 Forums
 Transact-SQL (2008)
 GO

Author  Topic 

arkiboys
Master Smack Fu Yak Hacker

1433 Posts

Posted - 2011-11-11 : 10:17:47
Hi,
Can you explain what Go does in sql?
It seems if you do not have GO in between your sql in query analyser, then everything is inside a transaction.
Am I right?
Thanks

nigelrivett
Master Smack Fu Yak Hacker

3385 Posts

Posted - 2011-11-11 : 10:22:18
>> Am I right?
no

It ends a batch. If you have a transaction a go doesn't affect it.
If you alter a structure then that (probably) isn't available until the next batch.
If you create a variable it has the scope of that batch.

Usually you add a go after create/drop/alter table, SP, function, view statements and that's about it.


==========================================
Cursors are useful if you don't know sql.
SSIS can be used in a similar way.
Beer is not cold and it isn't fizzy.
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2011-11-11 : 10:28:49
quote:
Originally posted by arkiboys

Hi,
Can you explain what Go does in sql?
It seems if you do not have GO in between your sql in query analyser, then everything is inside a transaction.
Am I right?
Thanks


GO is batch seperator
its also used for executing query in a loop

------------------------------------------------------------------------------------------------------
SQL Server MVP
http://visakhm.blogspot.com/

Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2011-11-11 : 10:30:31
quote:
Originally posted by arkiboys

Hi,
Can you explain what Go does in sql?
It seems if you do not have GO in between your sql in query analyser, then everything is inside a transaction.
Am I right?
Thanks


see

http://beyondrelational.com/blogs/madhivanan/archive/2008/08/06/another-use-of-go-command-in-sql-server-2005.aspx

------------------------------------------------------------------------------------------------------
SQL Server MVP
http://visakhm.blogspot.com/

Go to Top of Page

arkiboys
Master Smack Fu Yak Hacker

1433 Posts

Posted - 2011-11-11 : 10:33:16
Thank you all.
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2011-11-11 : 10:35:36
wc

------------------------------------------------------------------------------------------------------
SQL Server MVP
http://visakhm.blogspot.com/

Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2011-11-11 : 18:01:02
"It seems if you do not have GO in between your sql in query analyser, then everything is inside a transaction.
Am I right?
"

">> Am I right?
no

It ends a batch. If you have a transaction a go doesn't affect it.
"

Although please note this:

BEGIN TRANSACTION
GO
.... Do some stuff - within the transaction ...
GO
... Do some other stuff - also within the transaction ...
... BUT ... This "stuff" has a runtime error ...
GO
-- At this point you can safely ROLLBACK

... Do some MORE stuff
... At THIS point an implicit Rollback is called for all the previous statements in this batch
... and THEN the statements in this block are executed OUTSIDE THE TRANSACTION
GO
-- COMMIT or ROLLBACK will fail at this point

So you can NOT put a BEGIN TRANSACTION / COMMIT/ROLLBACK around a large block of statements (which includes GO statements) with the intention of using ROLLBACK if there is any error - because the first error will cause an implicit ROLLBACK and the rest of the statements will (attempt) to run outside any "transaction"

Batch Statements generated by Tools like RedGate incorporate very verbose statements in order to work around this ...
Go to Top of Page

GilaMonster
Master Smack Fu Yak Hacker

4507 Posts

Posted - 2011-11-12 : 04:02:07
Sorry Kristen, but that is NOT true. You absolutely can put Begin transaction ... commit/rollback around a block of statements that contain GO and the rollback at the end will roll back the whole lot.

The only time that what you say is true is when dealing with a very small number of DDL statements (and they really are very, very few) that automatically roll back transactions on failure. It is not the case with any DML and not the case with most DDL.

We've debated this before and I've proved it to you.

As a quick and dirty example:
CREATE TABLE t1 (id INT PRIMARY KEY);

BEGIN TRANSACTION
GO
CREATE TABLE t2 (id INT PRIMARY KEY);
GO

INSERT INTO t1 VALUES (1)

GO

INSERT INTO t1 VALUES (1) -- this will fail. Primary key violation

GO

INSERT INTO t1 VALUES (2)
INSERT INTO t1 VALUES (3)
INSERT INTO t2 VALUES (1)

GO

ROLLBACK

SELECT * FROM t1 -- 0 rows returned
go
SELECT * FROM t2 -- error, table creation was rolled back
go


That rollback at the end succeeds and rolls everything back to the begin transaction back

--
Gail Shaw
SQL Server MVP
Go to Top of Page

GilaMonster
Master Smack Fu Yak Hacker

4507 Posts

Posted - 2011-11-12 : 04:09:45
p.s. the complex scripts from the Redgate tools are because @@Error is only for the last statement, try-catch can't work across batches and variables are scoped at a batch level. Hence persisting the fact that there has been an error across batches is very difficult (though a temp table could be used, I've seen that work before)

--
Gail Shaw
SQL Server MVP
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2011-11-12 : 08:14:06
Sorry, you are quite right I should have been much clearer. "The only time that what you say is true is when dealing with a very small number of DDL statements (and they really are very, very few) that automatically roll back transactions on failure" those were the ones I was meaning to refer to as, if encountered, they wreck the rest of the script.

On DDL scripts we get them often enough that they are a problem. The one that seems to catch us out most often is creating an object that already exists. The scripts we are running assume the object does not exist, as the job of the script is to create the object in the first place. We could put EXISTS tests in place (but the scripts from SSMS don't include that when you script creation of a new object), but that's a lot of work for the hundreds, or more, of objects we create -- when 99.99% of the time they object won't exist.

But ... if the script breaks then some objects created later in the script WILL then exist if I try to re-run the script, so that' snot an option and generally we have to restore from backup or repeat it piecemeal.

I think its a significant issue with DDL scripts created by SSMS. But .. for us, its much quicker (and probably more accurate) than hand-building them; we could build them with something else, such as RedGate (although, personally, I don't have that) which produces a fail-proof script

So my "moan" is really at SSMS-generated scripts, but "user beware"

"p.s. the complex scripts from the Redgate tools are because @@Error is only for the last statement, try-catch can't work across batches and variables are scoped at a batch level. Hence persisting the fact that there has been an error across batches is very difficult (though a temp table could be used, I've seen that work before)"

The RedGate ones I have come across check if @@TRANCOUNT=0, i.e. transaction has terminated for some reason (including RedGate's own test for @@ERROR<>0), and if TRUE they insert a row into a #TEMP table and start a new BEGIN TRANSACTION.

Example:

CREATE TABLE #tmpErrors (Error int)
GO
BEGIN TRANSACTION
GO
... attempt a statement ...
IF @@ERROR<>0 AND @@TRANCOUNT>0 ROLLBACK TRANSACTION
GO
IF @@TRANCOUNT=0 BEGIN INSERT INTO #tmpErrors (Error) SELECT 1 BEGIN TRANSACTION END
GO
... repeat for other statements ...
-- At end:
IF EXISTS (SELECT * FROM #tmpErrors) ROLLBACK TRANSACTION
GO

The absence of a GOTO (or any other way that I know of to get to the end of the script) means that a #TEMP table seems to be the only way to "preserve" the fact that an error occurred, due to unexpected ROLLBACK, but the drawback is that all subsequent statements have to run (inside newly started BEGIN TRANSACTION's) in order to let the script run without causing side effects, because there is no GOTO / ABORT.

The method we use of "terminating" a large script is to issue a RAISERROR and a WAITFOR with a long duration to give us time to manually terminate the script. But its a PITA ... and usually we only put them in at points where we have previously discovered a potential failure during real-world usage

COMMIT -- Next step must be outside a transaction
GO

IF EXISTS (SELECT * from dbo.sysobjects WHERE id = object_id(N'[dbo].[SomeTable]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)
BEGIN
PRINT '***** "SomeTable" ALREADY EXISTS - DO NOT PROCESS THE NEXT "CREATE TABLE" SECTION *****'
RAISERROR(
N'*** MANUAL INTERVENTION REQUIRED(1) - NOTE ANY MESSAGES DISPLAYED AND THEN ABORT SCRIPT AND RESUME MANUALLY ***',
10, 1) WITH NOWAIT
RAISERROR (N'*** PRESS CANCEL NOW !!! ***', 10, 1) WITH NOWAIT
WAITFOR DELAY '01:00:00'
END
GO

BEGIN TRANSACTION -- Start transaction if the script continues
GO

(I realise we could only CREATE the [SomeTable] if it doesn't already exist, so this is just an example where we encounter something that shouldn't be and want to bail-out.)
Go to Top of Page
   

- Advertisement -