Rolled back but an error persists - sql

Semantics:
I am using PostGreSql 9.0.3 as my Dbms. Actually i was tried to accomplish one of the objectives assigned for me, which is to Raise Exception with some predefined message when some conditions failed in a IF - Statement inside my stored procedure. As a result of that exception, The Process should needs to be rolled back.
Syntax:
For r3 in select itemname,stock from stock s,items it where s.itemno=it.itemno and it.itemno=$2[I].itemno and s.stockpointno=$1.stockpointno loop
if xStock > r3.stock then
RAISE EXCEPTION '%', r3.itemname || ' decreased down from the low stock level';
end if;
End Loop;
where r3 is a record and xStock is a Double Precision Variable.
Then At the end of the stored procedure i just included the following code in order to roll
back the transactions happened.
Exception when raise_exception then rollback transaction;
The problem i am facing is when ever the manual exception getting raised, The following error bumps up.
DA00014:ERROR: XX000: SPI_execute_plan_with_paramlist failed executing query "rollback transaction": SPI_ERROR_TRANSACTION
Though the above error occured, transactions are not happened while i was checking in the tables. I don't know the exact reason why this particular error is raising when rolling back is in progress. Can anybody tell what may be the possible mistake which i was made in my code? And also suggest solutions to fix this issue.

While some database engines allow COMMIT or ROLLBACK inside a function or procedure, PostgreSQL does not. Any attempt to do that leads to an error:
ERROR: cannot begin/end transactions in PL/pgSQL
That includes code inside an exception block.
On the other hand, a RAISE EXCEPTION alone will abort the transaction with the function-supplied error message, so there's no need to trap your own exception. It would work as expected if you just removed your exception block.
As said by the plpgsql documentation in Trapping Errors:
By default, any error occurring in a PL/pgSQL function aborts
execution of the function, and indeed of the surrounding transaction
as well
You current code raises the exception, then traps it and fails in the exception block itself because of the forbidden ROLLBACK statement, which leads to the SQL engine aborting the transaction.

Related

ORA-02048 - Attempt to begin distributed transaction without loggin on

anyone know something about this error?
ORA-02048: attempt to begin distributed transaction without logging on
ORA-02063: preceding line from ..dblink
It occurs when I invoke since Java a PL/SQL Package that contains dblinks to access to other database for insert data. The dblink works good with other clauses, but not in this Package.
If I invoke this PL/SQL Package since TOAD, it works good.
I'm trying to reproduce this error, and I see this error arises from a pattern:
When I click the button which makes the PL run, the log shows me an error "ora-02292 integrity constraint child record found", and the next time I click the button, appears the error "ORA-02048", it is like the first error did lose the connection with remote database.
Thanks in advance
Without seeing a minimal testcase that demonstrates the problem, it's impossible to say.
However, looking up the error message:
-bash-4.1$ oerr ora 2048
02048, 00000, "attempt to begin distributed transaction without logging on"
// *Cause: client program must issue a distributed transaction login.
// *Action: contact support.
So, I'd recommend contacting Oracle support and opening an SR. But, the first thing they're likely to ask for is a working test case that demonstrates the problem.
The problem was thatI have different procedures, like that:
procedure1 -> (call) -> procedure 2 -> (call) -> procedure3
In procedure3 I have a clausure with dblink that insert into a remote table.
Procedure1 catchs the exceptions that may occur in procedure 2 and procedure3.
The problem is when an exception is throw in procedure3. In this case the rollback placed in the exception catch of procedure1, should finish the transaction, but it isn't working as I expected. The transaction is this case remains open and the second time in the procedure executions, oracle shows me the ORA-02048 error.
The solution was moving the exception catch into procedure3.

Is it a good thing to Raise Exceptions intentionally in PostgreSQL?

I am developing a PL function in Postgres, and in it I am modifying records of a table, according to some logic, then I execute a final query (basically counting), and if the number I get is positive, I throw an exception to rollback the transaction (since PostgreSQL's function doesn't support transactions explicitly).
So is this a good method to emulate transactions? Do you have better suggestions ?
PS: I am using PostgreSQL 9.2 but I am migrating to 9.3 soon, if this may help somehow.
If you wish to abort a transaction within a function, then yes, raising an exception is a good choice.
You can use subtransactions within PL/PgSQL functions by using BEGIN ... EXCEPTION blocks within the function. Use an inner BEGIN ... EXCEPTION block and within it RAISE an exception with a user defined SQLSTATE. Catch the exception in the EXCEPTION block.
A RAISE (of ERROR or higher) within a BEGIN ... EXCEPTION block will roll back work done within that block, as if you had used a SAVEPOINT and ROLLBACK TO SAVEPOINT.
Functions cannot force a rollback of the top level transaction; if you RAISE an exception, an outer pl/pgsql function can catch the exception in a BEGIN ... EXCEPTION block, or the client can use a ROLLBACK TO SAVEPOINT.
I have used this solution in the past. At issue is that the PLPGSQL language does not support the use of SAVEPOINT and ROLLBACK. Transactions wrap functions, not the other way around.
RAISE is the proper methodology to notify the client of some internal condition within a function. There are several levels of RAISE, the "worst" is EXCEPTION which will abort/rollback your transactions UNLESS something catches the exception and suppresses it.
For testing, use
`RAISE DEBUG 'some comment %', var;`
If you want to put something in your logs, but don't want to rollback, you can (typically) raise a WARNING. (Any level of RAISE can go to your logs, it depends on your configuration)

SQL: Try/Catch doesn't catch an error when attempting to access a table that it can't find

I've created a stored procedure that runs a number of commands to modify data. I only want to commit the transaction if everything succeeds. I'm doing this by using a try-catch block in the manner below (where my CATCH block in the real thing uses RAISERROR to return error messages):
BEGIN TRY
BEGIN TRANSACTION
UPDATE Table1 SET MyVarcharColumn = 'test'
UPDATE Table2 SET MyBitColumn = 1
UPDATE Table3 SET MyIntColumn = 42
COMMIT TRANSACTION
END TRY
CATCH
ROLLBACK TRANSACTION
END CATCH
That works the way I want it to. If, for example, I set MyBitColumn to 'b' instead of 1, the error is caught, control flows to the CATCH, and the transaction is not commited.
One issue I've noticed is that if, say, Table3 does not exist in the database then it errors out (invalid object name), but the CATCH block is never executed and the transaction remains open.
I want to handle this to take care of any (remote) possibility that a database gets modified (or something happens where this stored procedure is added properly, but one of the tables isn't).
How should I handle these error cases?
-Thanks for any help.
At the start of your script use SET XACT_ABORT
SET XACT_ABORT ON
When SET XACT_ABORT is ON, if a Transact-SQL statement raises a
run-time error, the entire transaction is terminated and rolled back.
I don't think that's going to be possible:
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.
Ref.
The following example shows how an object name resolution error
generated by a SELECT statement is not caught by the TRY…CATCH
construct, but is caught by the CATCH block when the same SELECT
statement is executed inside a stored procedure.
USE AdventureWorks2012;
GO
BEGIN TRY
-- Table does not exist; object name resolution
-- error not caught.
SELECT * FROM NonexistentTable;
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_MESSAGE() AS ErrorMessage;
END CATCH
The error is not caught and control passes out of the TRY…CATCH
construct to the next higher level.
EXECUTE ('SELECT * FROM NonexistentTable');

How to get inner errors from try/catch clause in SQL Server

I am running a stored procedure in SQL Server 2008 inside a try/catch. The stored procedure and the stored procs it calls raise a few errors but in the try/catch you only get the last error from the stored procedure that you are running.
Is there a way/trick to be able to somehow catch ALL the errors generated by child stored proc calls while running a particular stored procedure? (assume that you have no access to any stored procedures so you can't modify where they can write the error, i.e. you can't just change all the stored procedures to stop raising errors and instead write them to some table and in your catch read from that table)
Here is a good resource for how to deal with error handling in SQL Server.
http://www.sqlservercentral.com/articles/Development/anerrorhandlingtemplatefor2005/2295/
However, some of the methods require that you have the ability to change the code in order to capture the errors. There is really no way of getting around this. You can't just ignore the error, keep processing, and then come around later to deal with the error. In most, if not all, languages, exceptions have to be dealt with at the time the exception was raised. T-SQL is no different.
I personally use a stored procedure to log any error whenever it occurs. Here is what I use:
CREATE PROCEDURE [dbo].[Error_Handler]
#returnMessage bit = 'False'
WITH EXEC AS CALLER
AS
BEGIN
INSERT INTO Errors (Number,Severity,State,[Procedure],Line,[Message])
VALUES (
ERROR_NUMBER(),
ERROR_SEVERITY(),
ERROR_STATE(),
isnull(ERROR_PROCEDURE(),'Ad-Hoc Query'),
isnull(ERROR_LINE(),0),
ERROR_MESSAGE())
IF(#returnMessage = 'True')
BEGIN
select Number,Severity,State,[Procedure],Line,[Message]
from Errors
where ErrorID = scope_identity()
END
END
If you have stored procs that are raising more than one error, they need to be replaced no matter what. You probably have data integrity errors in your database. That is a critical, "everything needs to stop right now until this is fixed" kind of issue. If you can't replace them and they were incorrectly written to allow processing to continue when an error was reached, then I know of no way to find the errors. Errors are not recorded unless you tell them to be recorded. If the stored procs belong to a product you bought from another vendor and that's why you can't change them, your best bet is to change to a vendor that actually understands how to program database code because there is no salvaging a product written that badly.
You wouldn't have a Java or c# methods raising error after error. Why do you expect SQL to allow this? An exception is an exception
If the DB Engine is throwing errors then you have problems.
What I've done before is to separate testing and checking code: find out what is wronf first and throw one exception If no errors, do your writes.

Is it possible anyhow to raise system exception on catching exception manually?

I am writing a stored procedure where i m using try catch block.
Now i have a unique column in a table. When i try to insert duplicate value it throws exception with exception no 2627.
I want this to be done like this
if (exists(select * from tblABC where col1='value')=true)
raiseError(2627)--raise system error that would have thrown if i would have used insert query to insert duplicate value
EDIT:
I m using transaction which gets rollback on handling exception hence leading to increment of ##Identity value that got executed in previous queries b4 the exception occurred.
I want to check all such exception that could occur b4 actually inserting. For doing this, i would be checking for exception that could raise error manually using select statement with if else. Here i will be able to catch unique key violation but exception will not be occurred so i will be throwing exception deliberately here but that exception i want should be a system exception i.e error 2627
And which method will be better, using
insert query or checking for duplicate
value before insertion using Select
query ?
IS IT POSSIBLE ANYHOW TO RAISE SYSTEM
EXCEPTION ON CATCHING EXCEPTION
MANUALLY i.e THROWING SAME EXCEPTION THAT SQL WOULD HAVE THROWN
You can't raise system errors. RAISERROR(2627...) is illegal. Beside the fact that you're lying (no error 2627 occurred), you're missing the inserts into the message format.
Application should never rely on IDENTITY continuity, the fact that you complain that it 'increases the autoincrement' revels your application has a bug (in design for sure, if not in code). IDENTITY values may contain gaps, is part of their specifications.
As to what is better, to insert and catch, or to try to update: it depends on your prevalent pattern. If the value is likely to exist, the UPDATE first strategy is better. If the value is likely not to exist or if the probability is unknown it is better to INSERT and catch the error, for reasons of performance and, more importantly, correctness (SELECT check is never correct under concurrency).