I'm looking for a List of all possible exceptions which can occur for each SQL Command.
For example: If I have the following code:
Procedure p1
as
l_cnt number;
Begin
Select count(*)
Into l_cnt
From xyz;
Exceptions
When ... Then
...
End;
Now I'm wondering which exception can occur in this Select Into Statement. I know a few but are they all there is? That's why I'm looking for an overview of possible Exceptions per SQL.
A question on top would be: Is it recommended to catch all possible Exceptions raised by SQL Code inside PLSQL?
I know of "when others" which is the only way for me atm to catch "unknown" exceptions.
Of course if the list of possible exceptions for a SQL is very long I would only handle the relevant exeptions and catch the others by "when others".
To be honesty, your question is pretty common.
For example, you query can lead to the following exceptions:
TIMEOUT_ON_RESOURCE - A time out occurs while the database is waiting for a resource
STORAGE_ERROR - PL/SQL ran out of memory or memory was corrupted
I would suggest to learn predifined exceptions from official documentation and select suitable for each case.
Related
I am brand new to Postgresql and am trying to write a function that calls another function, and then returns -1 if that function had any errors. I am coming from a T-SQL background and essentially want the equivalent of
CREATE PROCEDURE [dbo].[p_newproc]
AS
BEGIN
EXEC p_seed_table
IF ##ERROR <> 0
RETURN -1
...
END
So far I have found that I am likely going to use something like the following:
CREATE OR REPLACE FUNCTION public.fn_newfunc()
RETURNS void
AS
$$
BEGIN
PERFORM fn_seed_table();
EXCEPTION
WHEN
SQLSTATE <> '00000'
RAISE EXCEPTION '-1';
End;
$$
LANGUAGE 'plpgsql';
Any advice would be appreciated. Thanks.
This is too long for a comment.
Both SQL Server and Postgres support exception handling. You chose not to use exception handling in the SQL Server code. You should make a conscious and informed decision about using exceptions (in either database).
SQL Server stored procedures return integers by default, and these can be used for status. Postgres doesn't have stored procedures, "only" stored functions, so you need to be a bit more explicit about the return values. The closest equivalent in Postgres to a stored procedure is a function that returns an integer.
There are pros and cons to switching over to exceptions rather than handling exceptions locally using return values (and be extra careful if you have transactions that span code blocks). I think exception handling is more robust in Postgres: SQL Server misses some types of exceptions.
However, you can implement either method in either scripting language. If you switch to using exceptions, think about the issues before doing so. That is, don't just reflexively make the switch. If you do switch to exception handling, also change the SQL Server code -- assuming you are maintaining both code bases.
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)
Shortly, I am wondering which of the following is the better practice:
to encapsulate my code in TRY/CATCH block and display the error message
to write own checks and display custom error messages
As I have read the TRY/CATCH block is not handling all types of errors. In my situation this is not an issue.
I am building dynamic SQL that executes specific store procedure. I can make my own checks like:
is the procedure that is going to be executing exists
are all parameters supplied
can be all values converted properly
or just to encapsulate the statement like this:
BEGIN TRY
EXEC sp_executesql #DynamicSQLStatement
SET #Status = 'OK'
END TRY
BEGIN CATCH
SET #Status = ERROR_MESSAGE()
END CATCH
Is there any difference if I make the checks on my own (for example performance difference) or I should leave this work to the server?
The reason I am asking is because in some languages (like JavaScript) the use of try/catch blocks is known as bad practice.
Typically it is going to be better to check for these things yourself than letting SQL Server catch an exception. Exception handling is not cheap, as I demonstrate in these posts:
Checking for potential constraint violations before entering SQL Server TRY and CATCH logic
Performance impact of different error handling techniques
Depending on the schema, volume, concurrency, and the frequency of failures you expect, your tipping point may be different, so at very high scale this may not always be the absolute most efficient way. But in addition to the fact that in most cases you're better off, writing your own error handling and prevention - while it takes time - allows you to fully understand all of your error conditions.
That all said, you should still have TRY / CATCH as a failsafe, because there can always be exceptions you didn't predict, and having it blow up gracefully is a lot better than throwing shrapnel everywhere.
A try/catch should only be used for critical errors. If there are possible errors that you can prevent by doing a simple if statement, you should do it. Don't rely on try/catch to make sure, for example, that a user entered a date in the correct format. Check that yourself.
Personally, if I get a critical exception like that, I'd prefer to see the call stack and where it happened. So, I only do a try/catch in the topmost layer of my project.
Using Try Catch Block you can still raise Custom Error Messages, Actually if you have Custom error Message then you can only show Custom error message you cannot sql server default error message. and you can also make use of many other error functions as well to get a lot more information about your error, Like
ERROR_LINE()
ERROR_MESSAGE()
ERROR_STATE()
ERROR_NUMBER()
ERROR_STATE(),
These functions can only be used in Catch block of TRY/CATCH block and makes our lifes a lot easier as a developer :)
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.
This is a pretty specific question, albeit possibly subjective, but I've been using this pattern very frequently while not seeing others use it very often. Am I missing out on something or being too paranoid?
I wrap all my UPDATE,DELETE,INSERT operations in stored procedures, and only give EXECUTE on my package and SELECT on my tables, to my application. For the UPDATE and DELETE procedures I have an IF statement at the end in which I do the following:
IF SQL%ROWCOUNT <> 1 THEN
RAISE_APPLICATION_ERROR(-20001, 'Invalid number of rows affected: ' || SQL%ROWCOUNT);
END IF;
One could also do this check in the application code, as the number of rows affected is usually available after a SQL statement is executed.
So am I missing something or is this not the safest way to ensure you're updating or deleting exactly what you want to, nothing more, nothing less?
I think this is a fine way to go. If the pl/sql proc is expected to always update/delete/insert a row and it's considered an error otherwise, then what better place to put this check than in the pl/sql proc itself? That way, no matter what client side code (C#, JAVA, PHP, Rails, etc.) uses this proc, you have this error check centralized in one place.
However, I'm not sure you need the check for an insert. If the insert fails, you should get some sort of DB exception, so no need to check for it explicitly unless you are wrapping the error in some other error message and re-raising it.
In most cases I'd use an ORM like Hibernate, which does a similar thing in order to handle Optimistic locking. Also it will use the PK in the where clause.
So I would consider this kind of stored procedure a waste of time:
- A lot of effort for minimal benefit
- Makes usage of tools like ORMs harder, which solve more and more important problems.