1. 程式人生 > >函式中的DML語句的執行問題--自治事務

函式中的DML語句的執行問題--自治事務

問題:寫一個函式,函式中要更新資料庫中的某個欄位,函式在使用時格式是:select funcName() from dual; 那麼此函式中如果含有update語句

函式:

create or replace function CalABGrpRearBounty()

return number is Result number;

begin

    update larearrelation set rearcommflag = 2 where rearcommflag = 1;

     commit;

end;

報:ORA-14551,不能在查詢語句中執行dml語句

開始以為函式本身有問題,其實不然,是因為select funcName() from dual; 這個語句的問題

解決:函式中使用自治事務

            自治事務實現的功能是自治事務的提交或回滾不影響當前的事務。同時自治事務也是看不到當前會話所做的未提交的修改的。

create or replace function CalABGrpRearBounty(tAgentCode laagent.agentcode%type,
                                              tAgentGrade latree.agentgrade%type
                                              )
return number is pragma autonomous_transaction

;

mResult number;
mAgentCode laagent.agentcode%type;
mFYCMin lawageradix.fycmin%type; -- 非本人推薦的獎金數量
mFYCMax lawageradix.fycmax%type; -- 本人推薦的獎金數量
mRecommendCount number;          -- 推薦次數
mRearCommFlag number;           

begin
mResult := 0;
     -- 查詢育成獎金標準
     select FYCMin into mFYCMin from lawageradix where agentgrade = tAgentGrade and wagecode = 'WA0009' and branchtype = 2;

     if(mFYCMin is not null and mFYCMin > 0)
     then
         begin
              select FYCMax into mFYCMax from lawageradix where agentgrade = tAgentGrade and wagecode = 'WA0009' and branchtype = 2;

              -- 查詢被育成人,存在育成關係,且未提傭,且計算日期在育成止期後
              -- rearcommflag=1:未進行佣金計算;rearcommflag=2:已進行過佣金計算;rearcommflag=3:已稽核。            
              declare cursor rearListCursor is
              select agentcode from larearrelation where rearagentcode = tAgentCode and rearflag = 1 and (rearcommflag = 1 or rearcommflag = 2);
              begin
                   open rearListCursor;
                   loop
                       fetch rearListCursor into mAgentCode;
                       exit when rearListCursor%notfound;

                       -- 查詢育成人是否推薦人
                       select count(*) into mRecommendCount from larecomrelation where agentcode = mAgentCode and recomagentcode = tAgentCode
                                                            and recomflag = 1;
                       if(mRecommendCount = 1)
                       then
                            mResult := mResult + mFYCMax;
                       else
                            mResult := mResult + mFYCMin;
                       end if;

                       -- 更新rearcommflag=2,表示已計算過佣金
                       select rearcommflag into mRearCommFlag from larearrelation where rearagentcode = tAgentCode and agentcode = mAgentCode and rearflag = 1;
                       if(mRearCommFlag = 1)
                       then
                           begin
                                update larearrelation set rearcommflag = 2 where rearcommflag = 1 and rearagentcode = tAgentCode and agentcode = mAgentCode and rearflag = 1 ;
                                commit;
                           end;
                       end if;
                      
                   end loop;
                   close rearListCursor;
              end;
         end;
     end if;
return(mResult);
end;

以下摘自:作者: 楊廷琨,  出處:blog, 責任編輯: 王曉晨,  2008-08-04 09:31

這兩天看了11g的CONCEPT文件的事務部分,發現自治事務還有一些以前沒有注意到的地方,這裡簡單總結一下。

  這一篇簡單描述一下自治事務可以使用的位置。

  自治事務可以使用在以下的位置:

  儲存過程和函式;

  本地過程和函式;

  包;

  物件方法;

  匿名塊的最頂層。

  其中過程、函式和包中使用自治事務很常見,大部分自治事務的情況都屬於這種情況。由於物件相對使用的比較少,所以物件方法中的自治事務也是比較少見的,不過由於物件中的方法和包中的儲存過程、函式十分相似,所以這種情況也是情理之中的。

  剩下的兩種情況,是以前所不瞭解的。從來沒有想過對於本地過程和函式也是可以定義為自治事務的,不過本地過程定義為自治事務是十分方便的功能,使得過程中需要用到自治事務的功能時,不必再額外定義一個自治事務的儲存過程,只需要在當前的過程中定義一個自治的本地過程就可以了。

  一個簡單的例子如下:

SQL> CREATE TABLE T_AUTO_TRANS (ID NUMBER, NAME VARCHAR2(30));

  表已建立。 

SQL> CREATE TABLE T_LOG (ID NUMBER, NAME VARCHAR2(30));

  表已建立。

  下面建立一個LOCAL PROCEDURE的自治事務的例子:

SQL> DECLARE
  2 PRAGMA AUTONOMOUS_TRANSACTION;
  3 BEGIN
  4 INSERT INTO T_LOG VALUES (1, 'AUTONOMOUS_TRANSACTION');
  5 COMMIT;
  6 END;
  7 /

  PL/SQL 過程已成功完成。

SQL> SELECT * FROM T_AUTO_TRANS;
  ID NAME
  ---------- ------------------------------
  1 TEST
  SQL> SELECT * FROM T_LOG;
  ID NAME
  ---------- ------------------------------
  1 AUTONOMOUS_TRANSACTION
  1 AUTONOMOUS_TRANSACTION
  SQL> ROLLBACK;

  回退已完成。

SQL> SELECT * FROM T_AUTO_TRANS;
  未選定行
SQL> SELECT * FROM T_LOG;
  ID NAME
  ---------- ------------------------------
  1 AUTONOMOUS_TRANSACTION
  1 AUTONOMOUS_TRANSACTION

  這種情況的意義沒有本地過程的大,不過對於編寫包含大量的SQL和PL/SQL的sql檔案還是有不少幫助的。

 Oracle 11g自治事務更像是在單獨的會話中執行,它的事務狀態不會影響當前的事務,它也不會看到當前事務沒有提交的修改。

   自治事務實現的功能是自治事務的提交或回滾不影響當前的事務。同時自治事務也是看不到當前會話所做的未提交的修改的。 

SQL> TRUNCATE TABLE T_AUTO_TRANS;

  表被截斷。

SQL> CREATE OR REPLACE PROCEDURE P_TEST AS
  2 BEGIN
  3 INSERT INTO T_AUTO_TRANS VALUES (2, 'TEST');
  4 FOR I IN (SELECT COUNT(*) CNT FROM T_AUTO_TRANS) LOOP
  5 DBMS_OUTPUT.PUT_LINE('P_TEST:' || I.CNT);
  6 END LOOP;
  7 END;
  8 /

  過程已建立。 

SQL> CREATE OR REPLACE PROCEDURE P_TEST_AUTO AS
  2 PRAGMA AUTONOMOUS_TRANSACTION;
  3 BEGIN
  4 INSERT INTO T_AUTO_TRANS VALUES (2, 'TEST');
  5 FOR I IN (SELECT COUNT(*) CNT FROM T_AUTO_TRANS) LOOP
  6 DBMS_OUTPUT.PUT_LINE('P_TEST_AUTO:' || I.CNT);
  7 END LOOP;
  8 COMMIT;
  9 END;
  10 /

  過程已建立。

SQL> INSERT INTO T_AUTO_TRANS VALUES (1, 'TEST');

  已建立 1 行。 

SQL> SET SERVEROUT ON
  SQL> EXEC P_TEST
  P_TEST:2

  PL/SQL 過程已成功完成。

SQL> EXEC P_TEST_AUTO
  P_TEST_AUTO:1

  可以看到,對於自治事務是看不到當前會話所作的未提交的修改的。

SQL> EXEC P_TEST
  P_TEST:4

  PL/SQL 過程已成功完成。

  而對於當前會話,由於自治事務的操作已經提交,因此之後的查詢是可以看到自治事務所進行的修改的。

  自治事務看不到當前會話的修改,那麼自治事務呼叫的過程是否能看到自治事務的修改呢: 

SQL> TRUNCATE TABLE T_AUTO_TRANS;

  表被截斷。

SQL> CREATE OR REPLACE PROCEDURE P_AUTO_TRANS AS
  2 PRAGMA AUTONOMOUS_TRANSACTION;
  3 BEGIN
  4 INSERT INTO T_AUTO_TRANS VALUES (1, 'TEST');
  5 INSERT INTO T_AUTO_TRANS VALUES (2, 'TEST');
  6 FOR I IN (SELECT COUNT(*) CNT FROM T_AUTO_TRANS) LOOP
  7 DBMS_OUTPUT.PUT_LINE('P_AUTO_TRANS:' || I.CNT);
  8 END LOOP;
  9 P_TEST;
  10 P_TEST_AUTO;
  11 COMMIT;
  12 END;

   過程已建立。  

SQL> INSERT INTO T_AUTO_TRANS VALUES (1, 'TEST');

  已建立 1 行。

SQL> EXEC P_AUTO_TRANS
  P_AUTO_TRANS:2
  P_TEST:3
  P_TEST_AUTO:1
  PL/SQL 

     過程已成功完成。

  建立一個自治事務,分別呼叫一個普通過程和一個聲明瞭自治事務的過程,結果可以看到,自治事務呼叫普通過程,可以看到自治事務所進行的修改,而對於自治事務呼叫的自治事務過程,是看不到自治事務所進行的修改的。

  從這一點看,自治事務更像是在單獨的會話中執行,它的事務狀態不會影響當前的事務,它也不會看到當前事務沒有提交的修改。

總結:要想在SELECT語句中對錶進行修改,可以使用自治事務(Autonomous TransactionsAT)。自治事務(Autonomous Transactions)是由另外一個事務呼叫的,這個叫事務做主事務(Main TransactionMT)。自治事務(Autonomous Transactions)的提交(commit)和回滾(rollback)並不影響主事務(MT)。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

相關推薦

ORACLE:SELECT語句裡呼叫函式使用DML語句進行UPDATE/INSERT/DELETE操作

需求: 公司一系統升級,要維護的資料庫表中已有資料,該表沒有序列、觸發器等。此表要直接插入一些資料,插入的資料為了和以前的資料相容(就是一樣)。該表主鍵的生成以前是在程式碼中分兩步進行的,即查詢、更新(現在要直接插入資料,不用服務端JAVA程式碼,不能用這個)。 做法: 本

Oracleselect語句執行過程

通過from子句中找到需要查詢的表 通過where子句進行非分組函式篩選判斷 通過group by子句完成分組操作 通過having字句完成組函式篩選判斷 通過select字句選擇顯示的列或表示式及組函式 通過order by字句進行排序操作

函式DML語句執行問題--自治事務

問題:寫一個函式,函式中要更新資料庫中的某個欄位,函式在使用時格式是:select funcName() from dual; 那麼此函式中如果含有update語句 函式: create or replace function CalABGrpRearBounty() ret

laravel查看執行的SQL語句

model http nec 條件 alt 今天 不能 conn obj 今天想查看laravel框架中執行的SQL語句,百度了一圈,才找到,這文檔真心看著不爽,下面上查看方法 DB::connection()->enableQueryLog();

oraclefor update語句執行時間過長的問題

oracle執行查詢語句SELECT s.sid, s.serial# FROM v$locked_object lo, dba_objects ao, v$session s WHERE ao.object_id = lo.object_id AND lo.session_id = s.sid 查出的兩個字

javascript奇怪的執行結果(立即執行函式

在下面的例子中,將IIFE賦值給一個變數message。message返回另外一個函式,該函式只是簡單地輸出變數x的值。有趣的事情是,當我們把變數x的初始值作為引數傳入函式時,可以在函式執行時所建立的閉包中捕獲變數x的值。無論在外部作用域中x的值發生了什麼變化,閉包將記住函式執行時變數x的值

javatry catch語句執行順序簡介

package com.string_lc; /** * @filename Test.java * @author l * @description */ public class Test { public static void main(String[] args) {

JS的自執行函式

轉自:https://www.cnblogs.com/zuiyirenjian/p/3535126.html 在JS中,也常常需要複用,將一些常見的操作封裝起來,目前看到的很多JS庫,比如JQuery就是非常典型的,那麼如何在JS中寫一個可複用的呢?雖然在JS中有類的這個說法,但是我對這個玩意還

javascript的立即執行函式(function(){…})()

javascript和其他程式語言相比比較隨意,所以javascript程式碼中充滿各種奇葩的寫法,有時霧裡看花,當然,能理解各型各色的寫法也是對javascript語言特性更進一步的深入理解。 ( function(){…} )()和( function (){…} () )是兩種javasc

使用mysqlbinlog從二進位制日誌檔案查詢mysql執行過的sql語句

前提MySQL開啟了binlog日誌操作1. 檢視MySQL是否開啟binlog(進mysql操作)  mysql> show variables like 'log_bin%';       2. 查詢binlog檔名 &nbs

MyBatis學習總結(六)---使用log4j2將sql語句執行記錄輸出控制檯和檔案

  在上一篇部落格中我簡單的介紹了在MyBatis中如何使用日誌,並給出了一個在MyBatis中使用log4j的示例。    MyBatis中日誌的使用及使用log4j示例   下面介紹在MyBatis中如何使用log4j2將sql語句執行記錄輸出控制

伺服器無法繼續執行事務,此會話的活動事務已由另外一個會話提交或終止。

//執行事務處理 public void DoTran() {  //建立連線並開啟  SqlConnection myConn=GetConn();  myConn.Open();  SqlCommand myComm=new SqlCo

ORACLE查詢語句執行順及where部分條件執行順序測試 Oracle的一些查詢語句及其執行順序 Select 語句執行順序以及如何提高Oracle 基本查詢效率

Oracle中的一些查詢語句及其執行順序 原文地址:https://www.cnblogs.com/likeju/p/5039115.html 查詢條件:1)LIKE:模糊查詢,需要藉助兩個萬用字元,%:表示0到多個字元;_:標識單個字元。2)IN(list):用來取出符合列表範圍中的資料。3)NOT I

dljd_007_jdbc程式設計的statement執行DML/DDL

一、使用statement的executeUpdate執行DML(增刪改)語句示例   package edu.aeon.jdbc; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManag

dljd_016_jdbc使用PreparedStatement執行DQL(查詢)語句

一、jdbc使用preparedStatement執行dql(查詢)語句示例    package edu.aeon.jdbc.crud; import java.sql.Connection; import java.sql.PreparedStatement; import java.

dljd_015_使用PreparedStatement執行crud之DML語句(增加操作)

一、使用jdbc進行DML語句之增加資料操作示例   package edu.aeon.jdbc.crud; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException

關於java switch 語句執行順序

首先來一個正常的demo int i = 2; switch (i) { case 1: System.out.println("1"); break; case 2: System.out.println("2"); break;

習題 11.1 將例11.1的程式片斷補充和改寫成一個完整、正確的程式,用公用繼承方式。在程式應包括輸入資料的函式,在程式執行時輸入num,name,sex,age,addr的值,程式應輸出以上。。

C++程式設計(第三版) 譚浩強 習題11.1 個人設計 習題 11.1 將例11.1的程式片斷補充和改寫成一個完整、正確的程式,用公用繼承方式。在程式中應包括輸入資料的函式,在程式執行時輸入num,n

dljd_027_增改刪在同一個事務的預設執行順序

一、測試增刪改在同一個事務中的預設執行順序示例 package edu.aeon.test; import org.hibernate.Session; import org.hibernate.Transaction; import edu.aeon.aeonutils.GetSe

java關於final,finally,finalize的區別?javafinally語句一定會執行嗎?

既然上一篇寫到繼承多型和封裝,那麼接著記一下final、finally和finalize的區別。最基礎的知識還是要鞏固牢靠的。 final:final作為java的修飾符,可以修飾類,變數和方法。被final修飾的類不能被繼承,修飾的變數不能更改值,修飾的方法不能被重寫。 finally:f