Oracle 原理: 過程和函數

 

一、存儲過程

PL/SQL分爲三個部分,聲明部分、可執行部分、異常處理部分,其中可執行部分是必須要有的。

創建過程的語法:

Create [or replace]  procedure 過程名  [(參數list)]
 As|Is
--聲明變量在這裏寫
BEGIN
--過程程序在這裏寫
EXCEPTION
--異常處理在這裏寫
END;

PL/SQL 子程序有點:

模塊化:將程序分解爲邏輯模塊

可重用性:可以被任意數目的程序使用

可維護性:簡化維護操作

安全性:通過權限設置,是數據更加安全

 

create or replace procedure insertBlob(ifilepath in  varchar2,ifilename  in varchar2  )
authid current_user is
       img_file bfile;
       img_blob blob;
       lob_length number;
       sqlcommand  varchar2(500); 
       isexit number;
begin
   ----動態SQL,需要相應權限 create table  read,write on directory等 ---
     --設置虛擬路徑
     sqlcommand :='create or replace directory PHOTOPATH as ''' ||ifilepath ||'''' ;
     dbms_output.put_line(ifilepath || ifilename);
     execute immediate sqlcommand;
      --獲取bfile文件
     img_file := bfilename('PHOTOPATH',ifilename);
       --打開文件
     dbms_lob.open(img_file);
     --獲取文件長度
     lob_length := dbms_lob.getlength(img_file);
     --判斷文件是否存在,先把blob設成empty_blob()
     select count(1) into isexit from file_lobtest t1 where t1.filepath = ifilepath;
     dbms_output.put_line('isexit'|| isexit);
     if isexit = 0 then 
        insert into file_lobtest values(ifilepath,null,empty_blob(),img_file);
        dbms_output.put_line('-------1');
     else 
        update file_lobtest t1 set bfile_content=img_file,blob_content=empty_blob() where t1.filepath = ifilepath;
        dbms_output.put_line('-------2');
     end if ;
       --然後賦值blob變量
     select blob_content into img_blob from file_lobtest t1 where t1.filepath = ifilepath;
       --加載blob
     dbms_lob.loadfromfile(img_blob,img_file,lob_length);
     --關閉文件
     dbms_lob.close(img_file);
     commit;
end;

存儲過程和 PL/SQL語法很接近。 存儲過程和函數的區別就是存儲過程不需要return ,可以通過out來返回多個值,而函數需要return 。存儲過程 要在過程語句中才能被調用,而函數可以在過程語句中調用也可以在SQL語句中被調用。

create or replace procedure coutP(i in number,ret out  varchar2)
authid current_user as 
   a varchar2(50);
begin
  a :='';
  ret :='';
  for j in 1..i loop
    a := a|| '*';
    ret := ret||a||chr(10);
  end loop;
 
end;
/
--------調用存儲過程-------
declare 
 arg1 varchar(100);
begin
 coutP(5,arg1);
  dbms_output.put_line(arg1);
end;

輸出結果:

二、函數寫法和過程差不多,只不過函數需要return 不能out,函數可以在過程語句中調用也可以在SQL語句中被調用。


create or replace function coutP_fun(i  number) return varchar2
authid current_user as 
   a varchar2(50);
   ret   varchar2(50);
begin
  a :='';
  ret :='';
  for j in 1..i loop
    a := a|| '*';
    ret := ret||a||chr(10);
  end loop;
 return ret;
end;
/
-----調用函數----

select coutP_fun(6) from dual;

輸出結果:

 

三、自主事物處理

當調用過程時,子過程如果發生回滾則會影響到,調用過程的最終結果:要想避免子過程的事物影響到父過程,需要在子過程中添加:PRAGMA AUTONOMOUS_TRANSACTION;  --寫在  is 和 begin 之間


create or replace procedure proc(i in number,ret out  varchar2)
authid current_user as 
   a varchar2(50);
   --PRAGMA AUTONOMOUS_TRANSACTION;
begin
  update salary_tbl s set s.salary=-100 where s.employer_nm='僱傭者2'; 
  a :='';
  ret :='';
  for j in 1..i loop
    a := a|| '*';
    ret := ret||a||chr(10);
  end loop;
  rollback;
end;
/
declare 
 arg1 varchar(100);
begin
  update salary_tbl s set s.salary=-1200 where s.employer_nm='僱傭者1'; 
  proc(5,arg1);
  dbms_output.put_line(arg1);
  commit;
end;
/
select * from salary_tbl where employer_nm in('僱傭者1','僱傭者2');

把PRAGMA AUTONOMOUS_TRANSACTION;註釋掉的結果就是數據保留了原樣,因爲proc的回滾不僅把 update salary_tbl s set s.salary=-100 where s.employer_nm='僱傭者1'; 而且把父程序的 update salary_tbl s set s.salary=-1200 where s.employer_nm='僱傭者1'; 也回滾掉了;

output結果:   select 的結果  保留了原樣。

把PRAGMA AUTONOMOUS_TRANSACTION;註釋打開後的結果

在自主事物處理中:主程序按順序執行,當執行到自主事物的子程序時,主程序事物暫停,對應的數據上鎖,子程序的事物開啓順序執行子程序,子程序執行完後,主程序繼續執行。

自主事物處理特徵: 1)與主事物處理的狀態無關 ;2) 提交或回滾都不影響主事物;3)自主事物處理的結果是對其他事物是可見的;4)能夠啓動其他自主事物處理

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章