| 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?noIt 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. |
 |
|
|
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 seperatorits also used for executing query in a loop------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/ |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
|
|
arkiboys
Master Smack Fu Yak Hacker
1433 Posts |
Posted - 2011-11-11 : 10:33:16
|
| Thank you all. |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2011-11-11 : 10:35:36
|
| wc------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/ |
 |
|
|
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?noIt ends a batch. If you have a transaction a go doesn't affect it."Although please note this:BEGIN TRANSACTIONGO.... 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 TRANSACTIONGO-- 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 ... |
 |
|
|
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 TRANSACTIONGOCREATE TABLE t2 (id INT PRIMARY KEY);GOINSERT INTO t1 VALUES (1)GOINSERT INTO t1 VALUES (1) -- this will fail. Primary key violationGOINSERT INTO t1 VALUES (2)INSERT INTO t1 VALUES (3)INSERT INTO t2 VALUES (1)GOROLLBACKSELECT * FROM t1 -- 0 rows returnedgoSELECT * FROM t2 -- error, table creation was rolled backgo That rollback at the end succeeds and rolls everything back to the begin transaction back--Gail ShawSQL Server MVP |
 |
|
|
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 ShawSQL Server MVP |
 |
|
|
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 scriptSo 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)GOBEGIN TRANSACTIONGO... attempt a statement ...IF @@ERROR<>0 AND @@TRANCOUNT>0 ROLLBACK TRANSACTIONGOIF @@TRANCOUNT=0 BEGIN INSERT INTO #tmpErrors (Error) SELECT 1 BEGIN TRANSACTION ENDGO... repeat for other statements ...-- At end:IF EXISTS (SELECT * FROM #tmpErrors) ROLLBACK TRANSACTIONGO 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 transactionGOIF 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'ENDGOBEGIN TRANSACTION -- Start transaction if the script continuesGO (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.) |
 |
|
|
|