Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Xavier.

Asked: March 06, 2003 - 7:16 pm UTC

Last updated: April 20, 2005 - 2:03 pm UTC

Version: 9.2.0.2.0

Viewed 10K+ times! This question is

You Asked

I have a stored proc that uses Execute Immediate to run a dynamic SELECT query into a variable. It has worked fine for a long time. However, when the query references a linked table, the procedure blows up with the indicated error. The error only happens if I use the pragma AUTONOMOUS_TRANSACTION (which I do because the real procedure does SELECT's on tables that may be mutating).

Here is a toy procedure that demonstrates the problem:

PROCEDURE TEST
IS
PRAGMA AUTONOMOUS_TRANSACTION; /* needed in actual proc */

vSQL_A VARCHAR2(2000) := 'SELECT tagname_cd from tagname WHERE tagname_cd=''FAC_GN''';
vSQL_B VARCHAR2(2000) := 'SELECT fac_gn from fac@ebmud WHERE fac_gn=TO_NUMBER(123)';
vTempStr VARCHAR2(2000);
BEGIN
/* works with vSQL_A, fails with vSQL_B */
execute immediate vSQL_A INTO vTempStr;
END;


Now I know about your general caveats and recommendations about using dynamic sql. But nonetheless it all worked great until I did a select on a linked table.



and Tom said...

you cannot use an autonomous transaction in a distributed transaction -- period, plain and simple.

Also, to use an autonomous transaction to get around a mutating table sounds very very very VERY suspicious to me. I would question

a) the need
b) the results

I've seen far too many people use this as the way to get around "mutating tables" only to totally miss the point. They are not able to enforce the business rules they believe they are -- data integrity is out the window.

I'd be interested in hearing what you are doing exactly that necessitates an a-tran to read over a mutating table. I find pretty much every time I can show a huge hole in the logic -- meaning the integrity you were trying to achieve is gone.

The mutating table constraint is not an error, it is protecting you from yourself.




Rating

  (5 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

OK, but can I push the autonomous transaction down

Xavier Irias, March 07, 2003 - 1:12 pm UTC

OK, if I can't use a distributed transaction WITHIN an autonomous transaction, and the PRAGMA is there to handle not the distributed SELECT query, but a different SELECT, it sounds like I could just push the autonomous transaction down into a separate stored proc, to minimize the scope of the AUTONOMOUS pragma? Sound right?

Re the need for and results of the autonomous transaction: I have two tables, call them Parent and Child, with one Parent row for zero to many Children. The parent row has a "group" column indicating what "group" the parent is in. Given a userid and a group, I have a function that returns True or False on group membership.

The business rule for updating either table is that you may only modify a child or parent if you belong to the same "group" as the child or parent. So when the proposed update is on a child, it is necessary to lookup the parent row in order to determine group membership. Since I am doing the check within a trigger, I use an autonomous transaction for the lookup because it's possible that the parent and child are both being modified within a single transaction (making the parent mutating). The autonomous nature of the transaction means that I see the parent as it existed before the current transaction started. If the parent did not even exist before the current transaction started, then the autonomous transaction finds no parent which can be handled fine.

Clearly the update logic would be simpler to code and test, and would perform better, if I used a stored proc and simply forbade direct UPDATE's to both tables. However from the point of view of higher-level code, the stored procs are an inferior interface (taken to an extreme, if we use stored procs for all data updates, why even have a SQL-compliant database). I think I understand the pros and cons of using stored procs versus trigger code, and I have chosen stored procs in cases where their benefits outweighed their negatives. The case in question here is just not one of those times, and I would like to make the trigger option work.




Tom Kyte
March 07, 2003 - 1:35 pm UTC

you do not need an atran, just as I thought.

What command would you be executing that in a single statement would modify both the parent and child.

mutating table constraints are statement level issues, NOT transaction level issues.

You would have to be issuing a single DML statement that modified both tables at the same time.

Tell me -- what statement could that be? I am failing to see the mutating table issue here.


Single statement causing updates to two tables

Xavier Irias, March 07, 2003 - 1:51 pm UTC

How about cascading logic? Either a parent trigger wants to cascade primary key changes to children for example, or a trigger-maintained value in the parent table, e.g. ChildCount, needs to be incremented or decremented during insert or delete of a child. The appropriate table then issues its own updates.

Though I must admit that when I look closely at the actual situation I face, I think I CAN do with the autonomous transaction as you said.

Tom Kyte
March 07, 2003 - 1:52 pm UTC

Either a parent trigger wants to cascade primary key
changes to children for example,

that'll mutate all by its lonesome...

or a trigger-maintained value in the parent
table, e.g. ChildCount, needs to be incremented or decremented during insert or
delete of a child.

that'll have no issues, try it....


I need a concrete example, then I can address it.


did you mean to so "i think i CAN do withOUT the atran"?

Yes that's what I meant

Xavier Irias, March 07, 2003 - 2:56 pm UTC

Yes, thank you.

ORA-06519: active autonomous transaction detected and rolled back

Giridhar, April 19, 2005 - 11:38 pm UTC

Hi Tom,
Description of oerr 6519 is as follows:
--------------------------------------------------------
Cause: Before returning from an autonomous PL/SQL block, all autonomous transactions started within the block must be completed (either committed or rolled back). If not, the active autonomous transaction is implicitly rolled back and this error is raised.

--------------------------------------------------------

It means that we need to have either commit or rollback in the trigger if we use autonomous_transaction pragma.

Is there any usage of having a trigger with AUTONOMOUS_TRANSACTION, without commit or rollback? If yes, can you please explain.
If not,Is it not possible for oracle to catch this error during compilation stage itself instead of allowing user to create the trigger and raise the exception during usage?

Thanks in advance.
Giridhar



Tom Kyte
April 20, 2005 - 6:49 am UTC

no - think about it, if you MUST commit or rollback any work.....


No it cannot catch it at compile time, it has to run the code:


if ( to_char(sysdate,'dy') = 'mon' )
then
commit;
end if;


there, an autonomous transaction that works on mondays.... the compiler cannot catch this.

Thanks Tom

Giridhar, April 20, 2005 - 2:03 pm UTC

Thanks Tom for the information and for quick reply.


More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library