May 18, 2004 at 11:33 am
I am getting an error when i issue a save transaction "Cannot issue SAVE TRANSACTION when there is no active transaction"
I am using this in a sp. This is what I am trying to do...
BEGIN TRAN ABC
INSERT INTO tblMaster
IF ERROR ROLLBACK TRAN ABC
GET SCOPE_ID
INSERT INTO tblDetail
IF ERROR ROLLBACK TRAN ABC
SAVE TRAN T1
UPDATE tblTemp
IF ERROR ROLLBACK TRAN T1
COMMIT TRAN ABC
May 18, 2004 at 11:37 am
If there is an error in the first item, a rollback will occur and there is no transaction. You don't want to do the save if the first rollback occurred.
Follow me on Twitter: http://www.twitter.com/way0utwest
Forum Etiquette: How to post data/code on a forum to get the best help
My Blog: www.voiceofthedba.com
May 18, 2004 at 11:44 am
My Bad,
All the Rollback and Save Transaction are in IF ELSE statements. I had a SET NOCOUNT ON which was causing a problem, something like
NO COUNT ON
BEGIN TRAN ABC
INSERT INTO tblMaster
IF ERROR ROLLBACK TRAN ABC
GET SCOPE_ID
INSERT INTO tblDetail
IF ERROR ROLLBACK TRAN ABC
ELSE SAVE TRAN T1
UPDATE tblTemp
IF ERROR ROLLBACK TRAN T1
COMMIT TRAN ABC
NO COUNT OFF
The problem is when i use the keyword GO after SET NOCOUNT ON I get errors "define param..." and when i take the keyword GO out I get the "Save Transaction" error.
Confused
Thanks
May 20, 2004 at 2:41 am
Where is "Begin Tran T1"..
It appears you are going from Tran ADC to Saving Tran T1
May 20, 2004 at 7:50 am
SET NOCOUNT ON | OFF can be used anywhere as many times as you want.
GO is a batch separator, so any local variables created with DECLARE are release when you issue a GO. Since your problem seems to be related to the structure of your code, you should be as precise as possible. At the very least, show the actual IF ELSE structure, including BEGIN and END. Post the exact code with any changes to table names, literal data, etc., as need for confidentiality.
I assumed you used the following format:
SET NOCOUNT ON
BEGIN TRAN ABC
INSERT INTO tblMaster
IF ERROR
ROLLBACK TRAN ABC
ELSE BEGIN
GET SCOPE_IDENTITY()
INSERT INTO tblDetail
IF ERROR
ROLLBACK TRAN ABC
ELSE BEGIN
SAVE TRAN T1
UPDATE tblTemp
IF ERROR
ROLLBACK TRAN T1
COMMIT TRAN ABC
END
END
SET NOCOUNT OFF
Mike
May 20, 2004 at 8:11 am
Here is what I have done.
CREATE PROC usp_Insert
@param 1 varchar(100), @param2 int, @param3 tinyint
AS
SET NOCOUNT ON
DECLARE @errStatus VARCHAR(100)
SET @errStatus = ''
BEGIN TRANSACTION ABC
INSERT tblMaster
IF @@ERROR <> 0
BEGIN
SET @errStatus = some value
ROLLBACK TRANSACTION ABC
GOTO ERRORHANDLER
END
ELSE
BEGIN
SCOPE_IDENTITY()
END
INSERT tblDetail
IF @@ERROR <> 0
BEGIN
SET @errStatus = some value
ROLLBACK TRANSACTION ABC
GOTO ERRORHANDLER
END
ELSE
BEGIN
SAVE TRANSACTION T1
END
UPDATE tblTemp1
IF @@ERROR <> 0
BEGIN
SET @errStatus = some value
ROLLBACK TRANSACTION T1
GOTO ERRORHANDLER
END
ELSE
BEGIN
SAVE TRANSACTION T2
END
END
UPDATE tblTemp2
IF @@ERROR <> 0
BEGIN
SET @errStatus = some value
ROLLBACK TRANSACTION T2
GOTO ERRORHANDLER
END
COMMIT TRANSACTION ABC
ERRORHANDLER:
SET @errStatus = some processing
RETURN @errStatus
SET NOCOUNT OFF
The thing that comes to my mind is would this transaction commit if there is a rollback to T1 ot T2 or would i need to change error handling to accomodate for that. I am explicitly committing transaction abc only once in the entire procedure.
May 20, 2004 at 9:30 am
Yes, if an error occurs in UPDATE tblTemp1 (after saving T1), then you jump to your error handler without committing or rolling back transaction ABC. Same thing could happen with an error on UPDATE tblTemp2.
Offhand, I don't see how you could get to the SAVE TRANSACTION statements without the transaction being given the code you've provided.
The purpose of SAVE TRANSACTION is rollback only part of transaction. If you immediately jump to your error handler and rollback everything (ROLLBACK TRAN ABC), there is no need for SAVE TRANSACTION.
If you want to commit ABC if the tblMaster and tblDetail inserts complete successfully (no matter what happens with the tblTemp1 and tblTemp2 inserts) and use the value of the identity column from the tblMaster insert as part of the tblTemp1 and tblTemp2 inserts, I would use two separate transactions. During the first transaction, save SCOPE_IDENTITY() into a local variable after the first insert.
Begin a second transaction for the tblTemp1 and tblTemp2 inserts, using the SCOPE_IDENTITY() local variable mentioned above.
The advantage of two transactions is that it frees up tblMaster and tblDetail a little sooner.
Viewing 7 posts - 1 through 6 (of 6 total)
You must be logged in to reply to this topic. Login to reply