環(huán)境
?
????????Oracle 11.2.0 + SQL Plus
?
問題
?
????????根據(jù)以下要求編寫函數(shù):將scott.emp表中工資低于平均工資的職工工資加上200,并返回修改了工資的總?cè)藬?shù)。PL/SQL中有更新的操作,執(zhí)行此函數(shù)報(bào)如下錯(cuò)誤:ORA-16551: 無法在查詢中執(zhí)行 DML 操作。
?
解決
?
????????在聲明函數(shù)時(shí)加上: ?PRAGMA AUTONOMOUS_TRANSACTION; ?并在執(zhí)行完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
--編寫函數(shù)
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 /
函數(shù)已創(chuàng)建。
--調(diào)用函數(shù),出現(xiàn)錯(cuò)誤
SQL> SELECT raise_sal() FROM DUAL;
SELECT raise_sal() FROM DUAL
*
第 1 行出現(xiàn)錯(cuò)誤:
ORA-14551: 無法在查詢中執(zhí)行 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 /
函數(shù)已創(chuàng)建。
--驗(yàn)證第一步:查詢薪水平均值
SQL> SELECT AVG(sal) FROM emp;
AVG(SAL)
----------
2543.75
--驗(yàn)證第二步:查詢薪水比平均薪水低的員工的總數(shù)
SQL> SELECT count(sal) FROM emp WHERE sal < (SELECT AVG(sal) FROM emp);
COUNT(SAL)
----------
8
--驗(yàn)證第三步:查詢數(shù)據(jù)
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行。
--驗(yàn)證第四步:調(diào)用函數(shù),如果為8,則實(shí)現(xiàn)功能
SQL> SELECT raise_sal() FROM dual;
RAISE_SAL()
-----------
8
--驗(yàn)證第五步:再次查詢表數(shù)據(jù)
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
?
?
引用文字——更好的理解自治事務(wù)
?
????????數(shù)據(jù)庫事務(wù)是一種單元操作,要么是全部操作都成功,要么全部失敗。在Oracle中,一個(gè)事務(wù)是從執(zhí)行第一個(gè)數(shù)據(jù)管理語言(DML)語句開始,直到執(zhí)行一個(gè)COMMIT語句,提交保存這個(gè)事務(wù),或者執(zhí)行一個(gè)ROLLBACK語句,放棄此次操作結(jié)束。事務(wù)的“要么全部完成,要么什么都沒完成”的本性會(huì)使將錯(cuò)誤信息記入數(shù)據(jù)庫表中變得很困難,因?yàn)楫?dāng)事務(wù)失敗重新運(yùn)行時(shí),用來編寫日志條目的INSERT語句還未完成。針對這種困境,Oracle提供了一種便捷的方法,即自治事務(wù)。自治事務(wù)從當(dāng)前事務(wù)開始,在其自身的語境中執(zhí)行。它們能獨(dú)立地被提交或重新運(yùn)行,而不影響正在運(yùn)行的事務(wù)。正因?yàn)檫@樣,它們成了編寫錯(cuò)誤日志表格的理想形式。在事務(wù)中檢測到錯(cuò)誤時(shí),您可以在錯(cuò)誤日志表格中插入一行并提交它,然后在不丟失這次插入的情況下回滾主事務(wù)。因?yàn)樽灾问聞?wù)是與主事務(wù)相分離的,所以它不能檢測到被修改過的行的當(dāng)前狀態(tài)。這就好像在主事務(wù)提交之前,它們一直處于單獨(dú)的會(huì)話里,對自治事務(wù)來說,它們是不可用的。然而,反過來情況就不同了:主事務(wù)能夠檢測到已經(jīng)執(zhí)行過的自治事務(wù)的結(jié)果。要?jiǎng)?chuàng)建一個(gè)自治事務(wù),您必須在匿名塊的最高層或者存儲(chǔ)過程、函數(shù)、數(shù)據(jù)包或觸發(fā)的定義部分中,使用PL/SQL中的PRAGMA AUTONOMOUS_TRANSACTION語句。在這樣的模塊或過程中執(zhí)行的SQLServer語句都是自治的。觸發(fā)無法包含COMMIT語句,除非有PRAGMA AUTONOMOUS_TRANSACTION標(biāo)記。但是,只有觸發(fā)中的語句才能被提交,主事務(wù)則不行。
我的郵箱
:
wgbno27@163.com
新浪微博
:
@Wentasy27
微信公眾平臺(tái)
:JustOracle(微信號:justoracle)
數(shù)據(jù)庫技術(shù)交流群
:336882565(加群時(shí)驗(yàn)證 From CSDN XXX)
Oracle交流討論組
:
https://groups.google.com/d/forum/justoracle
By Larry Wen
|
?
|
| @Wentasy 博文僅供參考,歡迎大家來訪。如有錯(cuò)誤之處,希望批評指正。原創(chuàng)博文如需轉(zhuǎn)載請注明出處,謝謝 :) [CSDN博客] |
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

