Execute update clause even with errors - sql

I'm doing some script testing and I want to make sure that if the Update Clause I'm testing in this Try Catch :
BEGIN TRY
BEGIN TRAN
UPDATE NAME
SET NAME.ADDBY =
(CASE WHEN NAME.ADDBY = 'CONVERSION' THEN 'CONVERTED'
WHEN NAME.ADDBY = 'CJDOG'THEN 'CJDAREME'
WHEN NAME.ADDBY = 'npalerm' THEN 'REALLYLONGDETAILEDTEXT'
ELSE NAME
END)
COMMIT TRAN
END TRY
BEGIN CATCH
IF ##TRANCOUNT >0
PRINT ERROR_MESSAGE()
ROLLBACK TRAN
END CATCH
PRINT ##TRANCOUNT
fails, that other rows are updated and only the ones that didn't error go through.
Currenty because it is in the TRY CATCH there is a ROLLBACK that makes sure nothing goes through.
But when I try to run just the UPDATE part the errors terminates the whole script, instead of updating those that do not cause an error, in this case npalerm is too long in the case.
Any Ideas?
I know its a long desc I could've just included the Update but for detailed purpose I included it in the Catch.

In order to update the rows individually and catch the errors on each row rather than catching errors on the entire table/view update, you would need to wrap the whole thing in a cursor.
Be aware that cursors are more resource intensive and slower than set-based commands.

Related

Stop a stored procedure from further execution once the condition is violated?

I have a following stored procedure and i want to abort it once the number of rows in fact table are not similar to the historical data. So i'm trying to do something like, till now it only sends the email to the users that the data is not same but i want to add an another feature, i.e to abort/stop the SP if the rows difference is more than 5%. But it's not working properly. Can anyone explain where i'm making the mistake? Following is the chunk of stored procedure where i'm making modifications:
SET XACT_ABORT ON;
Begin Try
Begin Transaction;
if (#delta_ok = 0)
set #email_body = #email_body+char(13)+char(10)+'ETL process has been stopped.'
Return
else
set #email_body = #email_body+char(13)+char(10)+'ETL process is copying the data .'
Commit Transaction;
Begin Catch
Rollback Transaction
End Catch
End Try
So my question is that if put "RETURN" inside the "if" statement would it stop the SP? Once the condition is violated? And pass to "ELSE" if the condition isn't fulfilled?
Your syntax is all over the place here. Using some formatting to add clarity will help considerably. Also you have an anti-pattern in your code I call Try/Squelch. You catch an error but then you swallow it and don't tell anybody it happened. When exceptions happen you need to handle them. That means you need to tell the calling program something went wrong, not just silently ingest the details so nobody knows it happened or how to fix it.
Begin Try
Begin Transaction;
if (#delta_ok = 0)
begin
set #email_body = #email_body + char(13) + char(10) + 'ETL process has been stopped.'
Return
end
else
begin
set #email_body = #email_body + char(13) + char(10) + 'ETL process is copying the data .'
Commit Transaction;
end
End Try
Begin Catch
Rollback Transaction
--you really need something here to log/audit and probably tell the calling program something failed.
End Catch

SQL Code Guard and nested transactions rollback?

I have a stored procedure that may be called from a transaction. When there is an exception I want to rollback the transaction (the top-level transaction). I would like to use something like this:
...procedure definition...
BEGIN
BEGIN TRY
--work&logic
END TRY
BEGIN CATCH
-- An error occurred!
IF ##TRANCOUNT > 0
ROLLBACK
END CATCH
END
The catch with this is, that the SQL Code Guard reports for this the warning EI020 - ROLLBACK TRANSACTION without BEGIN TRANSACTION. Is there a way to write this properly?

Linkserver update not working in Transaction

I am trying to do operation on my linked server
created one linked server , everything is ok
just observed one thing which I am not able to understand
if I run
update SERVER.testdb.[AAA].MyTable
set MyName= 'abc#pqr.com'
where ID=999
This works fine ,but
when i execute same code in following way
BEGIN TRY
BEGIN TRANSACTION TRF
update SERVER.testdb.[AAA].MyTable
set MyName= 'abc#pqr.com'
where ID=999
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION TRF
END CATCH
It shows The parameter is incorrect
Can anyone tell me why this is hapeening and what is solution ?

Understanding nested transaction SQL

I have this code:
begin transaction outside
go
begin transaction inside
go
print 'inside done'
commit transaction inside
update Action set IdUser = 9999999999999
commit transaction outside
This code throws an exception on purpose at "update Action set IdUser = 999...", because of a foreign key problem.
I wish to rollback in case anything wrong occurs. That's why I have an outside transaction. In real world, I have a SQL file with a lot of scripts, and I want to make sure all the scripts maintain in a transaction, so I want to wrap it in an outside transaction.
That code above is not working. It's printing "inside done", and then throws an exception. This print could be a big insertion.
What's going on? How do I solve it?
Just try your query using the below template:
begin tran outside
begin try
begin tran inside
print 'inside done' --Insert\Update\Delete
Update Action set IdSuer = 999999999
END TRY
BEGIN catch
rollback tran inside
rollback tran outside
GOTO FINISH
END catch
commit tran inside
commit tran outside
:FINISH
print 'END'

why the same try catch block have two different results

I want to rollback all statements in the CATCH block when the error is encountered in the TRY block:
BEGIN TRY
begin transaction
create table t3(a int )
insert into t3 values(1)
insert into t3 values(1,2) --error occur
insert into t3 values(3)
END TRY
BEGIN CATCH
--just take care of rollback
IF ##TRANCOUNT <> 0
BEGIN
PRINT 'in catch,ROLLING BACK';
ROLLBACK
END
END CATCH
go
At first the error is caught since the PRINT in the CATCH block works. However, after several changes back and forth, the error seems not be caught in the CATCH any more since no more printing happens.
Therefore, I open a new query and execute the same thing. This time error can be caught again!!
Sorry about the big images
When you run this code in a tool like management studio, your transaction is mantained for your SPID (assigned to a query window).
So the inconsistent reult issue is because you don't close the transaction on all of your code paths (lets say the rollback dosn't get reached), your transaction is still active the next time you run the script.
If you add IF ##TRANCOUNT <> 0 rollback transaction to the begining of your script you will have a consistent output.
Also notice that the try catch block is not meant to catch errors at statement compile level.
If you replace your error by a division by zero for example (print 1 / 0) the catch will work properly.
In MSDN
The following types of errors are not handled by a CATCH block when they occur at the same level of execution as the TRY…CATCH construct:
Compile errors, such as syntax errors, that prevent a batch from
running.
Errors that occur during statement-level recompilation, such as object name resolution
Errors that occur after compilation because of deferred name resolution.