Functions with LANGUAGE sql
are basically just batch files with plain SQL commands in a function wrapper (and therefore atomic, always run inside a single transaction) accepting parameters. Currently (including pg 9.5) all statements in an SQL function are planned at once, which is subtly different from executing one statement after the other and may affect the order in which locks are taken.
For anything more, as Jack wrote, the most mature language is PL/pgSQL (LANGUAGE plpgsql
). It works well and has been improved with every release over the last decade, but it serves best as glue for SQL commands. It is not meant for heavy computations (other than with SQL commands).
PL/pgSQL functions execute queries like prepared statements. Re-using cached query plans cuts off some planning overhead and makes them a bit faster than equivalent SQL statements, which may be a noticeable effect depending on circumstances.
This carries the advantages and disadvantages of prepared statements - as discussed in manual. For queries on tables with uneven data distribution and varying parameters dynamic SQL with EXECUTE may perform better because the gain from an optimized execution plan for the given parameter is bigger than the loss due to re-planning every time.
PostgreSQL 9.2 brought a major improvement in this area: The planner still caches execution plans for the duration of the session, but only after repeated calls have shown no significant gain from re-planning every time. So you get the best of both worlds performance-wise most of the time without (ab)using EXECUTE
for this purpose any more. Details in What's new in PostgreSQL 9.2 of the PostgreSQL Wiki.
You can win big with server side functions when you prevent additional round-trips to the database server from your application. Have the server execute as much as possible at once and only return a well defined result.
Avoid nesting of complex functions, especially table functions (RETURNING SETOF record
or TABLE (..)
). Functions are black boxes posing as optimization barriers to the query planner. They are optimized separately, not in combination with the outer query, which makes the planning simpler, but may result in redundant work. Also, cost and result size of functions cannot be predicted effectively.
The exception to this rule are simple SQL functions (LANGUAGE sql
), which can be "inlined". Read more about how the query planner works in this presentation by Neil Conway (advanced stuff).
In PostgreSQL a function always automatically runs inside a single transaction. All of it succeeds or nothing. If an exception occurs, everything is rolled back. But there is error handling ...
Here is a somewhat conservative but informative review of the capabilities of PL/pgSQL by the Czech PostgreSQL community. Note that it is a bit outdated by now (written for 8.1) and PL/pgSQL has seen a number of major improvements since.
I have written thousands of plpgsql functions over the years.