While creating complex procedures the whole function is treated as a transaction or If I just put the whole function in a begin ... end. so If any of the intermediate queries fail there will be no problem in system. So do I need any error reporting ? or IF ... ELSE checking for error reporting ? (assuming foreign key/unique/etc.. constraints are properly done)
Do/should I need to raise an error by myself if duplicate key value violates unique constraint or I should rely on database engine ?
are there any patterns to follow while writing stored procedures while developing Business logic into it ?
I am using PostgreSql and PL/PgSQL and I used to do ORM before
As I understand it you are writing functions to execute from your client code. The entirety of a function execution will always be within one transaction, whether or not you explicitly
BEGINa transaction, although you can use subtransactions in plpgsql by coding aBEGIN/ENDblock with anEXCEPTIONclause. Such subtransactions are not free, so you want to use them only when really needed.Where invariants necessary to enforce business rules can be stated declaratively, that is almost always better than enforcing them with imperative code in a trigger.
CHECKconstraints,PRIMARY KEYconstraints,FOREIGN KEYconstraints,UNIQUEconstraints, and (a feature unique to PostgreSQL)EXCLUSIONconstraints should all be used instead of trigger code when they cover the use case.If you are using PostgreSQL version 9.1 or later, the biggest decision to make before you get started is what strategy you will use for dealing with race conditions between concurrent transactions. The two main choices are whether to try to track all possible conflicts and deal with the issues in application code, or use just serializable transactions (you can make that default in your postgresql.conf file) and let PostgreSQL sort things out. The best write-up I’ve seen on the former is here: http://www.postgresql.org/files/developer/concurrency.pdf while links regarding the latter are:
http://www.postgresql.org/docs/current/interactive/mvcc.html
http://wiki.postgresql.org/wiki/SSI
If you use
SERIALIZABLEor evenREPEATABLE READtransactions you should run queries in some way that provides generalized handling of serialization failures; that is, if the transaction throws an exception with SQLSTATE set to ‘40001’ or ’40P01′ you should rollback the failed transaction and retry it from the start. You don’t want to embed the logic for that in application code each place you run a query. Many development frameworks these days allow transactional annotations which make this easy to implement. We only use serializable transactions at our shop, and it really does simplify things to know that if you can show that a transaction does the right thing by itself, it will do the right thing in any mix of transactions without any special coding to ensure that (beyond handling serialization failures as mentioned above).Note that due to the use of Serializable Snapshot Isolation the performance of PostgreSQL using serializable transactions is very close to less strict isolation levels for many workloads; if you’ve been shying away from the idea because of fears about blocking and deadlocks — don’t. Serializable transactions in PostgreSQL 9.1 don’t have those problems like databases using strict two-phase locking (S2PL) do.
Full disclosure: In a joint effort with Dan R.K. Ports of MIT, and based on papers by Michael J. Cahill et all of Sidney University, I helped implement Serializable Snapshot Isolation for PostgreSQL version 9.1, because we needed the functionality at my workplace. I don’t get any financial benefit from anyone else using it, but I personally feel this is generally the way to go. That is more, I hope, the reason I worked on the feature rather than a result of having worked on the feature.