In a DB2 SQL function, is there an equivalent to the Finally block in JAVA and .Net..? - db2

In DB2-400 v7.3, do functions or procedures have an equivalent to the Finally block as found in JAVA..? To quote the documentation:
The Finally block always executes when the try block exits.
It's used for cleanup purposes needed by that section of code. In a DB2 function, it could be used for dropping temporary objects, such as Declared global temporary tables.
If DB2 doesn't have such a feature, it's not the end of the world. It can easily be simulated in code.

Global Temporary Tables go away when the job ends, so no need to clean them up. SQL does not have a try() catch() block, so no there is no finally clause either.
You can write stored procedures in Java if you need that functionality, but I would expect those to be less performant as SQL stored procedures are compiled using C (which also doesn't have a finally block).
Alternatively you could write your stored procedures with RPGLE sub-procedures which do have an on-exit block which runs when the sub-procedure ends whether that is a normal or an abnormal end.

Related

PostgreSQL: Allow only one instance of stored procedure to run at a time

I have a stored procedure on Postgres, which processes large data and takes a good time to complete.
In my application, there is a chance that 2 processes or schedulers can run this procedure at same time. I want to know if there is a built in mechanism in db to allow only instance of this procedure to run at db level.
I searched the internet, but didn't find anything concrete.
There is nothing built in to define a procedure (or function) so that concurrent execution is prevented.
But you can use advisory locks to achieve something like that.
At the very beginning of the procedure, you can add something like:
perform pg_advisory_lock(987654321);
which will then wait to get the lock. If a second session invokes the procedure it will have to wait.
Make sure you release the lock at the end of the procedure using pg_advisory_unlock() as they are not released when the transaction is committed.
If you use advisory locks elsewhere, make sure you use a key that can't be used in other places.

PostgreSQL - implicit transactions analogue

I am using PostgreSQL 10 from RDS (AWS).
So note that I don't have full permissions to do whatever I want.
In PostgreSQL I have some functions written in PL/pgSQL.
From my experience in these function I cannot start/commit/rollback transactions. In a DO block I cannot do that either.
Is that correct? So what is the logic behind this... seems PostgreSQL expects each function to be called in the context of an existing transaction. Right?
But what if I want every statement in my function to be executed in a separate (short) transaction i.e. to have a behavior something like AUTOCOMMIT = ON?
I found some extension which maybe can do that but I am not sure.
I don't know if it's relevant.
https://www.postgresql.org/docs/10/ecpg-sql-set-autocommit.html
Isn't there a standard way of doing this in Postgres without the need to download and install additional packages/extensions?
Again: I want every statement in my function to be executed in a separate (short) transaction i.e. to have a behavior something like AUTOCOMMIT = ON.
So I want something like this:
https://learn.microsoft.com/en-us/sql/t-sql/statements/set-implicit-transactions-transact-sql?view=sql-server-2017
All statements in a function run in the same transaction, and no plugin can change that.
You can use procedures from v11 on, but you still have to explicitly manage transactions then.
I suspect that the best thing would be to run your functions on the database client, where you have autocommit automatically, rather than as a function in the database.

Why is not possible to use Commit and rollback in a PostgreSQL procedure?

I am creating procedures on a PostgreSQL database. I read about is not possible to use rollback inside these procedures.
Why?
Is it possible to use commit?
I guess that this is related with ACID properties, but what if we have two insert operations in a procedure. If the second fails the second one gets a rollback?
Thank you.
Postgres' overview gives a hint by explaining how their functions are different than traditional stored procedures:
Functions created with PL/pgSQL can be used anywhere that built-in functions could be used. For example, it is possible to create complex conditional computation functions and later use them to define operators or use them in index expressions.
This makes it awkward to support transactions within functions for every possible situation. From the docs:
Functions and trigger procedures are always executed within a transaction established by an outer query... However, a block containing an EXCEPTION clause effectively forms a subtransaction that can be rolled back without affecting the outer transaction.
If you were to have two INSERTs in a function, the first can be wrapped in an EXCEPTION block to catch any errors and decide if the second should be executed.
You are correct. You cannot rollback transactions that were started prior to the procedure from within the procedure. In addition, a transaction cannot be created within the procedure either. You would receive this error:
ERROR: cannot begin/end transactions in PL/pgSQL
SQL state: 0A000
Hint: Use a BEGIN block with an EXCEPTION clause instead.
As this error states, and as Matt mentioned, you could use an exception block to essentially perform a rollback. From the help:
When an error is caught by an EXCEPTION clause, the local variables of the PL/pgSQL function remain as they were when the error occurred, but all changes to persistent database state within the block are rolled back.
Alternatively, you could call the procedure from within a transaction, and roll that back if necessary.

DB2 and PL/1: Avoid redundancy by creating a reference to the appropriate cursor, work with it

I'm writing a PL/1 subroutine that reads data from DB2. Depending on the input, it uses one of 3 cursors. These have to be opened, fetched, closed, etc. On every of these cursor-specific operations I have to specify its name. This leads to very redundant code, because the remaining operations are exactly the same for every case.
Is it possible to create a reference, to which I would assign the appropriate cursor? Then I could use this to perform the necessary tasks only once.
Because of safety-related restrictions, I'm not allowed to use dynamic (prepared) SQL.
And is there a reference containing all commands I can use in my EXEC SQL statements?
Thanks in advance
David
And is there a reference containing all commands I can use in my EXEC SQL statements?
IBM has documentation for DB2, which contains an SQL reference for the product.

Is it possible to obtain the SQL statements generated by Class::DBI?

I want to find the exact SQL statements that are generated by a Perl ORM package such as Class::DBI. I am not looking for SQL generated for simple inserts and deletes, but for row modifications that result from slightly complicated object manipulations (inserting rows in a table which is a child of a row in a parent table, for example)
Is there some way to get it?
Class::DBI uses DBI under the hood, so you can enable tracing of all SQL statements via an environment variable:
DBI_TRACE=3=dbi.log your-perl-script
Or inside of Perl, before executing any statements:
use DBI;
DBI->trace(2, 'dbi.log');
See http://metacpan.org/pod/DBI#TRACING
Since you said "such as"…
You can set the environment variable DBIC_TRACE to 1 if you are using DBIx::Class (which has a Class::DBI compatibility layer).