環境
?
????????Oracle 11.2.0 + SQL Plus
?
問題
?
????????根據以下要求編寫函數:將scott.emp表中工資低于平均工資的職工工資加上200,并返回修改了工資的總人數。PL/SQL中有更新的操作,執行此函數報如下錯誤:ORA-16551: 無法在查詢中執行 DML 操作。
?
解決
?
????????在聲明函數時加上: ?PRAGMA AUTONOMOUS_TRANSACTION; ?并在執行完DML后 COMMIT 。
?
操作日志
?
--登錄到Oracle C:\Users\Wentasy>sqlplus wgb SQL*Plus: Release 11.2.0.1.0 Production on 星期六 6月 29 15:32:21 2013 Copyright (c) 1982, 2010, Oracle. All rights reserved. 輸入口令: 連接到: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production With the Partitioning, OLAP, Data Mining and Real Application Testing options --編寫函數 SQL> CREATE OR REPLACE FUNCTION raise_sal 2 RETURN NUMBER 3 IS 4 v_num NUMBER:=0; 5 v_avg emp.sal%TYPE; 6 BEGIN 7 SELECT AVG(sal) INTO v_avg FROM emp; 8 UPDATE emp SET sal=sal+200 WHERE sal < v_avg; 9 v_num:=SQL%ROWCOUNT; 10 RETURN v_num; 11 END raise_sal; 12 / 函數已創建。 --調用函數,出現錯誤 SQL> SELECT raise_sal() FROM DUAL; SELECT raise_sal() FROM DUAL * 第 1 行出現錯誤: ORA-14551: 無法在查詢中執行 DML 操作 ORA-06512: 在 "WGB.RAISE_SAL", line 8 --加上PRAGMA AUTONOMOUS_TRANSACTION和COMMIT。 SQL> CREATE OR REPLACE FUNCTION raise_sal 2 RETURN NUMBER 3 IS 4 PRAGMA AUTONOMOUS_TRANSACTION; 5 v_num NUMBER:=0; 6 v_avg emp.sal%TYPE; 7 BEGIN 8 SELECT AVG(sal) INTO v_avg FROM emp; 9 UPDATE emp SET sal=sal+200 WHERE sal < v_avg; 10 v_num:=SQL%ROWCOUNT; 11 COMMIT; 12 RETURN v_num; 13 END raise_sal; 14 / 函數已創建。 --驗證第一步:查詢薪水平均值 SQL> SELECT AVG(sal) FROM emp; AVG(SAL) ---------- 2543.75 --驗證第二步:查詢薪水比平均薪水低的員工的總數 SQL> SELECT count(sal) FROM emp WHERE sal < (SELECT AVG(sal) FROM emp); COUNT(SAL) ---------- 8 --驗證第三步:查詢數據 SQL> SELECT ename, sal FROM emp; ENAME SAL ---------- ---------- SMITH 1600 ALLEN 2400 WARD 2050 JONES 2975 MARTIN 2050 BLAKE 2850 CLARK 2450 KING 5000 TURNER 2300 JAMES 1750 FORD 3000 ENAME SAL ---------- ---------- MILLER 2100 已選擇12行。 --驗證第四步:調用函數,如果為8,則實現功能 SQL> SELECT raise_sal() FROM dual; RAISE_SAL() ----------- 8 --驗證第五步:再次查詢表數據 SQL> SELECT ename, sal FROM emp; ENAME SAL ---------- ---------- SMITH 1800 ALLEN 2600 WARD 2250 JONES 2975 MARTIN 2250 BLAKE 2850 CLARK 2650 KING 5000 TURNER 2500 JAMES 1950 FORD 3000 ENAME SAL ---------- ---------- MILLER 2300 已選擇12行。
?
?
參考資料
?
????????http://blog.csdn.net/gigiouter/article/details/7616627
?
?
引用文字——更好的理解自治事務
?
????????數據庫事務是一種單元操作,要么是全部操作都成功,要么全部失敗。在Oracle中,一個事務是從執行第一個數據管理語言(DML)語句開始,直到執行一個COMMIT語句,提交保存這個事務,或者執行一個ROLLBACK語句,放棄此次操作結束。事務的“要么全部完成,要么什么都沒完成”的本性會使將錯誤信息記入數據庫表中變得很困難,因為當事務失敗重新運行時,用來編寫日志條目的INSERT語句還未完成。針對這種困境,Oracle提供了一種便捷的方法,即自治事務。自治事務從當前事務開始,在其自身的語境中執行。它們能獨立地被提交或重新運行,而不影響正在運行的事務。正因為這樣,它們成了編寫錯誤日志表格的理想形式。在事務中檢測到錯誤時,您可以在錯誤日志表格中插入一行并提交它,然后在不丟失這次插入的情況下回滾主事務。因為自治事務是與主事務相分離的,所以它不能檢測到被修改過的行的當前狀態。這就好像在主事務提交之前,它們一直處于單獨的會話里,對自治事務來說,它們是不可用的。然而,反過來情況就不同了:主事務能夠檢測到已經執行過的自治事務的結果。要創建一個自治事務,您必須在匿名塊的最高層或者存儲過程、函數、數據包或觸發的定義部分中,使用PL/SQL中的PRAGMA AUTONOMOUS_TRANSACTION語句。在這樣的模塊或過程中執行的SQLServer語句都是自治的。觸發無法包含COMMIT語句,除非有PRAGMA AUTONOMOUS_TRANSACTION標記。但是,只有觸發中的語句才能被提交,主事務則不行。
我的郵箱 : wgbno27@163.com 新浪微博 : @Wentasy27 微信公眾平臺 :JustOracle(微信號:justoracle) 數據庫技術交流群 :336882565(加群時驗證 From CSDN XXX) Oracle交流討論組 : https://groups.google.com/d/forum/justoracle By Larry Wen
![]() |
![]() ![]() |
@Wentasy 博文僅供參考,歡迎大家來訪。如有錯誤之處,希望批評指正。原創博文如需轉載請注明出處,謝謝 :) [CSDN博客] |
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
