在执行一个有读写的函数调用的sql查询时,报错:

ORA-14551: cannot perform a DML operation inside a query

 如图:

 

经查,

 对数据库有写操作(INSERT、UPDATE、DELETE、CREATE、ALTER、COMMIT)的函数,是无法简单的用SQL来调用的.

使用"自主事物",可以解决这个问题.

其实"自主事物"的功能,主要是解决回滚时,标记了PRAGMA AUTONOMOUS_TRANSACTION;的代码块不受外面调用的事物作用.

在解决触发器更新不成功时,如果按默认,记录日志的也将回滚,用该方法强制记录日志,效果较好.

 

以下为转载:

建立自由性交易使用名为autonomous_transaction的编译指示(编译命令,, #include), 这个编译命令要放在declare里面.

 

Delcare or replace procedure procedure_name(params, types)

 

AS

 

PRAGMA AUTONOMOUS_TRANSACTION; 

当程序执行的时候,pl/sql 会把autonomous_transaction当成独立存在的区域来处理.

用途是用在记录程序事件,不影响程序的进行.


一切用pl/sql 代码说话

/* Formatted on 2006/04/27 14:05 (Formatter Plus v4.8.7) */

 

--test autonomous transaction

 

CREATE TABLE logging_infos(log_info VARCHAR2(200), log_time DATE);

 

COMMIT ; 

/* Formatted on 2006/04/27 14:05 (Formatter Plus v4.8.7) */

 

--create autonomous transaction procedure

CREATE OR REPLACE PROCEDURE logging_info (

 

log_info_in VARCHAR2,

 

log_time_in DATE)

 

--If your procedure's name is exit in oracle( DB) , then you cann't use it to declare a procedure with the same name

 

AS

 

PRAGMA AUTONOMOUS_TRANSACTION;

 

BEGIN

 

INSERT INTO logging_infos

 

(log_info, log_time)

 

VALUES (log_info_in, log_time_in); 

COMMIT;

 

END;

 

 

  books;

 

 

 --create main procedure  

CREATE OR REPLACE PROCEDURE book_insert (

 

isbn_in VARCHAR2,

 

title_in VARCHAR2,

 

summary_in VARCHAR2,

 

author_in VARCHAR2,

 

date_published_in DATE,

 

page_count_in NUMBER)

 

AS

 

BEGIN

 

INSERT INTO books(isbn, title, author, date_published,page_count)

 

VALUES (isbn_in, title_in, author_in, date_published_in,age_count_in); 

-- call autonomous transcation

 

logging_info ('aaron_sys', SYSTIMESTAMP);

 

ROLLBACK;

 

--rollback for main procedure , not the autonomous transcation

 

EXCEPTION

 

WHEN OTHERS

 

THEN

 

dbms_ouput.put_line (SQLERRM);

 

END; 

--test the main procedure   

BEGIN

 

book_insert ('ISBN987654321',TEST2','summary:ddddd','Aaron',O_DATE ('2006-04-25', 'yyyy-mm-dd'),88);

 

END;

 

 

 --successfuly completed  

SELECT *

 

FROM books; ---doesn't have the add info

 

SELECT *

 

FROM logging_infos; --the logging info is added .

 

 自动交易(autonomous_transaction 繁体版本的书,简体翻译成自由性交易或事前交易,还是觉得自由性交易比较好) , 一定要用commit or rollback, 如果不用的结果就是:

 可以编译,但是在执行的时候会提示:ORA-06519: active autonomous transaction detected and rolled back

ORA-06512: at "SYS.LOGGING_INFO", line 10

ORA-06512: at "SYS.BOOK_INSERT", line 15

ORA-06512: at line 2

 建立自由性交易使用名为autonomous_transaction的编译指示(编译命令,, #include), 这个编译命令要放在declare里面.

 

Delcare or replace procedure procedure_name(params, types)

 

AS

 

PRAGMA AUTONOMOUS_TRANSACTION;

当程序执行的时候,pl/sql 会把autonomous_transaction当成独立存在的区域来处理.

用途是用在记录程序事件,不影响程序的进行.

 

 

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

在触发器中操作触发此触发器的表,用PRAGMA AUTONOMOUS_TRANSACTION选项。

15.1为何使用自治事务 无法回滚的审计

一般情况下利用触发器禁止某些对表的更新等操作时,若记录日志,则触发器最后抛出异常时会造成日志回滚。利用自治事务可防止此点。

避免变异表

即在触发器中操作触发此触发器的表

在触发器中使用DDL 写数据库

对数据库有写操作(INSERT、UPDATE、DELETE、CREATE、ALTER、COMMIT)的存储过程或函数是无法简单的用SQL来调用的,此时可以将其设为自治事务,从而避免ORA-14552(无法在一个查询或DML中执行DDL、COMMIT、ROLLBACK)、ORA-14551(无法在一个查询中执行DML操作)等错误。需要注意的是函数必须有返回值,但仅有IN参数(不能有OUT或IN/OUT参数)。

开发更模块化的代码

在大型开发中,自治事务可以将代码更加模块化,失败或成功时不会影响调用者的其它操作,代价是调用者失去了对此模块的控制,并且模块内部无法引用调用者未提交的数据。

15.2 如何工作 事务控制

DECLARE整个块都是属于父事务的,自治事务从离PRAGMA后的第一个BEGIN开始,只要此BEGIN块仍在作用域,则都属于自治事务。例如在DECLARE模块中声明一个写数据库的函数,则此函数虽然在自治事务所在存储过程执行,但其属于父事务;而自治事务中调用的任何函数和存储过程、激发的任何触发器等均为此自治事务的一部分。

自治事务可以嵌套,嵌套深度等只受INIT.ORA参数TRANSACTIONS(同时并发的事务数,缺省为SESSIONS的1.1倍)制约。

作用域

1. 包中的变量

自治事务可看到并修改父事务的变量,父事务也会察觉到这一改变,且不存在回滚问题。

2. 会话设置/参数

自治事务与父事务共享同一个会话环境,通过ALTER SESSION作的修改对整个会话均有效。但SET TRANSACTION是事务级的,仅对提起修改的事务有效。

3. 数据库修改

父事务已提交的修改对自治事务可见,未提交的对自治事务不可见,自治事务的修改对父事务是否可见取决于隔离级别(Isolation Level)。

对于游标,取决于其打开的位置,若其在父事务中打开,则之前父事务未提交的修改对其是有效的,在自治事务中这些修改也可见;而在自治事务中打开,则父事务未提交的修改不可见。

若使用缺省的READ COMMITTED隔离级别,则自治事务的修改对父事务可见;若改用SERIALIZABLE,则不可见。

4. 锁

父事务与自治事务是完全不同的事务,因此无法共享锁等。

结束一个自治事务必须提交一个COMMIT、ROLLBACK或执行DDL。

保存点无法在自治事务中回滚到父事务中的一个保存点,只能在内部使用保存点。

15.3 最后说明 不支持分布式事务截至8.1.7在自治事务中不支持分布式事务

仅可用PL/SQL 全部事务回滚若自治事务出错,则全部回滚,即便父事务有异常处理模块。

事务级临时表每个会话仅一个事务可访问事务级临时表(多个会话中的事务可并发操作)。

15.4 可能遇到的错误
ORA-06519 – 检查到活动自治事务,回滚——退出自治事务时没有提交、回滚或DDL操作

ORA-14450 – 试图访问正在使用的事务级临时表

ORA-00060 – 等待资源时检查到死锁

posted on 2012-09-26 15:31  敌敌  阅读(749)  评论(0编辑  收藏  举报