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)能够启动其他自主事物处理

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