ORACLE_存儲過程一

存儲過程就是對業務關係複雜的sql語句的封裝,sql語句以程序塊的形式被封裝到了數據庫中,寫好之後無論是java、還是.net都可以向使用sql一樣使用這就是數據庫開發。

oracle 存儲過程的基本語法

create or replace  procedure testPro(
  arg1 in number,  --in 傳遞參數
  arg2 out number, --out 返回參數
  arg3 in out number -- in out 傳遞和返回參數 
)
create or replace procedure testPro(
     inarg in number,
     outarg out number,
     inoutarg in out number
)is v_localvaliable number;
begin 
  --分配inarg給v_localvaliable
  v_localvaliable :=inarg;
  --分配7給inarg這是不合法的,因爲聲明是in
  inarg:=7;
  --分配7給outarg這是合法的,因爲聲明是out
  outarg:=7;
  --分配outarg給v_localvaliable 合法
  v_localvaliable:=outarg;
  --分配inoutarg給v_localvaliable 合法 in out 
  v_localvaliable:=inoutarg;
  --分配7給inoutarg 合法 in out
  inoutarg:=7;
end testPro;
create or replace procedure delemp(
   v_empno in emp.empno%type
)as
no_result exception;

begin 
   delete from emp where empno=v_empno;
   if SQL%notfound then 
      raise no_result;
   end if;
   dbms_output.put_line('編碼爲'||v_empno||'的員工已被除名!');
   exception 
       when no_result then 
          dbms_output.put_line('你需要的數據不存在');
       when others then 
          dbms_output.put_line('發生其它錯誤');
end delemp;


1. 使用%TYPE

在許多情況下,PL/SQL變量可以用來存儲在數據庫表中的數據。在這種情況下,變量應該擁有與表列相同的類型。例如,students表的first_name列的類型爲VARCHAR2(20),我們可以按照下述方式聲明一個變量:

DECLARE

       v_FirstName VARCHAR2(20);

但是如果first_name列的定義改變了會發生什麼(比如說表改變了,first_name現在的類型變爲VARCHAR2(25))?那就會導致所有使用這個列的PL/SQL代碼都必須進行修改。如果你有很多的PL/SQL代碼,這種處理可能是十分耗時和容易出錯的。

這時,你可以使用”%TYPE”屬性而不是將變量類型硬性編碼。

例如:

DECLARE

       v_FirstName students.first_name%TYPE;

 

通過使用%TYPE,v_FirstName變量將同students表的first_name列的類型相同(可以理解爲將兩者邦定起來)。



--創建存儲過程
create or replace procedure  testPro
(
   param1 in number, --參數
   param2 in number
)is 
  variable1 integer :=0; --變量
  variable2 date ;
begin 

end testPro


--將select查詢結果存入到變量中,可以同時將多個列存儲到多個變量中,必須有一條記錄否則
--拋出異常(如果沒有記錄拋出NO_DATA_FOUND)
begin
select col1,col2 into 變量1,變量2 from table1 where xxx;
exception  when NO_DATA_FOUND then xxx;
end;
--if 判斷
if v_test=1 then 
begin 
  do someing
end;
end if;
--while 循環
while v_test=1 loop
begin 
xxxxx
end ;
end loop;
--變量賦值
v_test:=123;
--用for in 使用 cursor 
... 
is 
cursor cur is select * from xxx;
begin
  for cur_result in cur loop
    begin 
      v_sum:=cur_result.列名1+cur_result.列名2;
    end;
  end loop; 
end ;
--帶參數的cursor
cursor c_user(c_id number) is select name from user where typeid=c_id;
open c_user(變量值);
loop 
fetch c_user into v_name;
exit fetch c_user%notfound;
do someing 
end loop;
close c_user;


關於oracle存儲過程的若干問題備忘

1.在oracle中,數據表別名不能加as,如:
select a.appname from appinfo a;-- 正確
select a.appname from appinfo as a;-- 錯誤
 也許,是怕和oracle中的存儲過程中的關鍵字as衝突的問題吧
2.在存儲過程中,select某一字段時,後面必須緊跟into,如果select整個記錄,利用遊標的話就另當別論了。
  select af.keynode into kn from APPFOUNDATION af where af.appid=aid and af.foundationid=fid;-- 有into,正確編譯
  select af.keynode from APPFOUNDATION af where af.appid=aid and af.foundationid=fid;-- 沒有into,編譯報錯,提示:Compilation 
  Error: PLS-00428: an INTO clause is expected in this SELECT statement

3.在利用select...into...語法時,必須先確保數據庫中有該條記錄,否則會報出"no data found"異常。
   可以在該語法之前,先利用select count(*) from 查看數據庫中是否存在該記錄,如果存在,再利用select...into...
4.在存儲過程中,別名不能和字段名稱相同,否則雖然編譯可以通過,但在運行階段會報錯
 select keynode into kn from APPFOUNDATION where appid=aid and foundationid=fid;-- 正確運行
select af.keynode into kn from APPFOUNDATION af where af.appid=appid and af.foundationid=foundationid;-- 運行階段報錯,提示
ORA-01422:exact fetch returns more than requested number of rows
5.在存儲過程中,關於出現null的問題
假設有一個表A,定義如下:
create table A(
id varchar2(50primary key not null,
vcount number(8not null,
bid varchar2(50not null -- 外鍵 
);
如果在存儲過程中,使用如下語句:
select sum(vcount) into fcount from A where bid='xxxxxx';
如果A表中不存在bid="xxxxxx"的記錄,則fcount=null(即使fcount定義時設置了默認值,如:fcount number(8):=0依然無效,fcount還是會變成null),這樣以後使用fcount時就可能有問題,所以在這裏最好先判斷一下:
if fcount is null then
    fcount:=0;
end if;
這樣就一切ok了。
6.Hibernate調用oracle存儲過程
        this.pnumberManager.getHibernateTemplate().execute(
                new HibernateCallback() {
                    public Object doInHibernate(Session session)
                            throws HibernateException, SQLException {
                        CallableStatement cs = session
                                .connection()
                                .prepareCall("{call modifyapppnumber_remain(?)}");
                        cs.setString(1, foundationid);
                        cs.execute();
                        return null;
                    }

                }
);

 

原文:http://www.cnblogs.com/happyday56/archive/2007/07/05/806830.html

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