1. 程式人生 > >Oracle資料庫學習筆記四——儲存過程的值傳遞和引用傳遞

Oracle資料庫學習筆記四——儲存過程的值傳遞和引用傳遞

程式語言中的4種子例程:
由兩種行為定義,即形式值是否返回以及引數列表是值傳遞還是引用傳遞。
如果返回輸出,子例程就是函式,如果不返回,就是過程。
所以4中子例程為:
1.值傳遞函式
2.引用傳遞函式
3.值傳遞過程
4.引用傳遞過程


pl/sql值傳遞過程由下列5條規則定義:
1.所有形參必須使用in模式定義為只寫變數。(只能傳入,不能傳出)
2.所有形參必須是區域性作用域的變數,不能再過程執行期間改變。(不能給in模式的引數賦值)
3.所有形參可使用任意有效的sql或pl/sql資料型別
4.所有形參可以有預設的初值
5.任何從sql查詢到函式的系統引用遊標型別的強制轉換都是不可寫的,因此必須通過in模式引數進行傳遞。

  這包括哪些作為顯示遊標變數傳遞的以及使用cursor函式的強制轉換。

 --值傳遞:呼叫時接受值的副本,不返回輸出變數。 
 --使用值傳遞過程跨單個事務作用域管理多個DML語句。
 
 create or replace procedure add_user(
   username varchar2,
   age number,
   address varchar2,
   street_address varchar2
 )  is
 v_id number;
 
 --宣告內部函式(內部pl/sql塊) 從指定序列中獲得下一個值,使用了本地動態sql
 function get_sequence_value(sequence_name varchar2) return number is
    pragma autonomous_transaction;
    id_value number;
    statement varchar2(2000);
 begin
    statement :='begin'                              ||chr(10)
              ||' select '||sequence_name||'.nextval'||chr(10)
              ||' into :id_value'                    ||chr(10)
              ||' from dual;'                        ||chr(10) 
              ||'end;';   
    execute immediate statement using out id_value;
    return id_value;
  end get_sequence_value;
begin
    savepoint add_user;       --設定儲存點
   
    v_id :=get_sequence_value('SQ_USER');
    
    insert into tb_user(userid,name,age) values(v_id,username,age);
      
    if address is not null then
         --向地址表中插入值
         if street_address is not null then
            --向街道表中插入值
          end if;
    end if;
    
    exception
       when others then
          rollback to add_user;   --回滾到儲存點
          raise_application_error(-20001,sqlerrm);  --丟擲異常
end add_user;

--引用傳遞過程
--被呼叫時接受值的副本,不返回輸出變數,可改變實參的值。返回實參引用給呼叫程式單元。
pl/sql引用傳遞過程由下列5條規則定義:
1.必須至少有一個形參通過使用out或in out模式定義。
2.所有形參在過程操作中可更改的區域性作用域變數。
3.所有形參可使用任意有效的sql或pl/sql資料型別。
4.所有in模式形參可以有預設的初值。
5.任何從sql查詢到過程的系統引用遊標型別的強制轉換都是不可寫的,因此必須通過in模式引數進行傳遞。
  (即作為引數的系統引用遊標不能再寫入資料,只能是in模式的引數)
--例:引用傳遞過程
 function get_sequence_value(sequence_name varchar2) return number is
    pragma autonomous_transaction;
    id_value number;
    statement varchar2(2000);
 begin
    statement :='begin'                              ||chr(10)
              ||' select '||sequence_name||'.nextval'||chr(10)
              ||' into :id_value'                    ||chr(10)
              ||' from dual;'                        ||chr(10) 
              ||'end;';   
    execute immediate statement using out id_value;
    return id_value;
  end get_sequence_value;
  
  
 create or replace procedure add_user(
   username varchar2,
   age number,
   userid out number,   --輸出引數(引用傳遞)
 )  is
 v_id number;
begin
    savepoint add_user;       --設定儲存點
   
    userid :=get_sequence_value('SQ_USER');  --為輸出引數賦值
    
    insert into tb_user(userid,name,age) values(userid,username,age);
     
    exception
       when others then
          rollback to add_user;   --回滾到儲存點
          raise_application_error(-20001,sqlerrm);  --丟擲異常
end add_user;