ORACLE存儲過程,函數,包,游標


1、  PL/SQL語句塊

PL/SQL語句塊只適用於Oracle數據庫,使用時臨時保存在客戶端,而不是保存在數據庫。

基本語法:

Sql代碼   收藏代碼
  1. declare  
  2.   變量聲明、初始化  
  3. begin  
  4.   業務處理、邏輯代碼  
  5. exception  
  6.   異常捕獲  
  7. end;  

 
變量聲明:<變量名>  <類型及長度>  [:=<初始值>]
            例:v_name varchar2(20):=’張三’;

2、  循環語句

loop循環語法:

Sql代碼   收藏代碼
  1. loop  
  2.   exit  when  表達式  
  3. end loop;  

 
while循環語法:

Sql代碼   收藏代碼
  1. while 表達式  
  2.   loop  
  3.   end loop;  

 
for循環語法:

Sql代碼   收藏代碼
  1. for  <變量>  in  <變量取值范圍(小值..大值,如1..100)> loop  
  2. end loop;  

 
    for循環的變量可不做聲明及初始化。

3、  if判斷語句

基本語法:

Sql代碼   收藏代碼
  1. if  <表達式>  then  
  2. …  
  3. else  if  <表達式>  then  
  4. …  
  5. else  
  6. …  
  7. end  if;  
  8. end  if;  

 
例:

Sql代碼   收藏代碼
  1. declare  
  2.   v_identity number(4):=0;  
  3. begin  
  4.   loop  
  5.     if v_identity=1 then  
  6.       dbms_output.put_line('v_identity=1');  
  7.     else if v_identity=3 then  
  8.       dbms_output.put_line('v_identity=3');  
  9.     else if v_identity=6 then  
  10.       exit;  
  11.     else  
  12.       dbms_output.put_line('v_identity is not 1 or 3');  
  13.     end if;  
  14.     end if;  
  15.     end if; -- 注意,有多少個if就要有多少個end if結束標志。  
  16.   
  17.     v_identity:=v_identity+1;  
  18.   
  19.   end loop;  
  20.   
  21. exception  
  22.   when others then dbms_output.put_line('error!');  
  23. end;  

 

4、  分支case

基本語法:

Sql代碼   收藏代碼
  1. case  <變量>  
  2. when  常量  then  
  3. …  
  4. when  常量  then  
  5. …  
  6. else  
  7.       …  
  8. end case;  

 
例:

Sql代碼   收藏代碼
  1. declare  
  2.   v_number number(4):=3;  
  3.   v_string varchar(20):='abc';  
  4. begin  
  5.   case v_number  
  6.     when 1 then  
  7.       dbms_output.put_line('v_number is '||1);  
  8.     when 2 then  
  9.       dbms_output.put_line('v_number is '||2);  
  10.     when 3 then  
  11.       dbms_output.put_line('v_number is '||3);  
  12.   
  13.   end case;  
  14.   
  15.   case v_string  
  16.     when 'ab' then  
  17.       dbms_output.put_line('v_string is '||'ab');  
  18.     when 'bc' then  
  19.       dbms_output.put_line('v_string is '||'bc');  
  20.     else -- 缺省匹配  
  21.       dbms_output.put_line('v_string is other value');  
  22.   end case;  
  23.   
  24. exception  
  25.   when others then dbms_output.put_line('error!');  
  26. end;  

 
5、  異常(exception)

聲明異常語法:<異常名>  exception;
拋出異常語法:raise  <異常名>;
捕獲異常語法:when  <異常名>  then  異常處理語句;

例:

Sql代碼   收藏代碼
  1. declare  
  2.   v_input varchar2(1):='&throw';-- 動態輸入  
  3.   v_exception_1 exception; -- 自定義異常  
  4.   v_exception_2 exception;  
  5.   others exception; -- 系統異常  
  6.   
  7. begin  
  8.   if v_input='1' then  
  9.     raise v_exception_1; -- 拋出異常  
  10.   else if v_input='2' then  
  11.     raise v_exception_2;  
  12.   else  
  13.     raise others;  
  14.   end if;  
  15.   end if;  
  16.   
  17. exception  
  18.   -- 捕獲異常  
  19.   
  20.   when v_exception_1 then dbms_output.put_line('throw exception: v_exception_1');  
  21.   when v_exception_2 then dbms_output.put_line('throw exception: v_exception_2');  
  22.   when others then dbms_output.put_line('throw exception: others');  
  23.   
  24. end;  

 
6、  游標(cursor)

聲明游標語法:cursor  <游標名>  is  select語句;
聲明ref游標語法:<游標名>  is  ref  cursor;
打開游標語法:open  <游標名>;
移動游標並獲取數據語法:fetch  <游標名>  into  <用於保存讀取的數據的變量的名>;
關閉游標語法:close  <游標名>;
游標屬性(游標的屬性必須在關閉游標之前):

 %isopen: 判斷游標是否打開
 %notfound: 找不到數據時
 %found:
 %rowcount: 返回當前游標已掃描的數據行數量

游標分類:1、顯示游標(自定義游標);2、隱示游標(系統游標);3、REF游標

例:

Sql代碼   收藏代碼
  1. declare  
  2.   v_row test%rowtype; -- 匹配t_test表中一行所有的數據類型  
  3.   cursor v_cur is  
  4.     select * from test;-- 聲明游標  
  5. begin  
  6.   open v_cur;-- 打開游標  
  7.   loop  
  8.     fetch v_cur into v_row;-- 將游標所在行的數據轉存到v_row中  
  9.     exit when v_cur%notfound; -- 當游標到最后一行時跳出  
  10.     dbms_output.put_line('id = '||v_row.t_id||'  name = '||v_row.t_name||'  msg = '||v_row.t_msg);  
  11.   end loop;  
  12.   close v_cur;-- 關閉游標  
  13. exception  
  14.   when others then dbms_output.put_line('throw exception: others');  
  15. end;  

 
-- REF游標 --

Sql代碼   收藏代碼
  1. create or replace package upk_select_test  
  2. as   
  3. type uc_test is ref cursor; -- 聲明ref游標  
  4. end upk_select_test;  
  5.   
  6. -- 存儲過程中調用ref游標,並將查詢結果以游標的方式返回  
  7. create or replace procedure up_select_test_2  
  8. (uc_result out upk_select_test.uc_test)  
  9. is  
  10. begin  
  11.   open uc_result for select * from t_test;  
  12. end up_select_test_2;  

 
7、  通配類型操作符

%type: 通配某行某列數據類型,如v_name t_test.t_name%type;通配表t_test中的t_name。
%rowtype: 通配一行所有列的數據類型,如 v_row t_test%rowtype;匹配t_test表中一行所有的數據類型。

8、  存儲過程(procedure)

基本語法:

Sql代碼   收藏代碼
  1. create  procedure  <過程名>(<參數列表,無參時忽略>)  
  2. as|is  
  3.   變量聲明、初始化  
  4. begin  
  5.   業務處理、邏輯代碼  
  6. exception  
  7.   異常捕獲、容錯處理  
  8. end  <過程名>;  

 
參數:<參數名> in|out|in out  <參數類型,無長度說明> ,如:v_name  varchar2

in:入參
     out:出參
     in out:出入參

注:as|is表示as或is

調用語法:
1)、exec  <過程名>;
2)、execute  <過程名>;
3)、在PL/SQL語句塊中直接調用

例:

Sql代碼   收藏代碼
  1. create or replace procedure up_wap(v_param1 in out varchar2,v_param2 in out varchar2)  
  2. is  
  3. v_temp varchar2(20);  
  4. begin  
  5.   dbms_output.put_line('交換前參數1:'||v_param1||'  參數2:'||v_param2);  
  6.   v_temp:=v_param1;  
  7.   v_param1:=v_param2;  
  8.   v_param2:=v_temp;  
  9.   dbms_output.put_line('交換后參數1:'||v_param1||'  參數2:'||v_param2);  
  10.   
  11. exception  
  12.   when others then dbms_output.put_line('There is a error when the procedure up_wap executing!');  
  13. end up_wap;  

 
-- 調用存儲過程

Sql代碼   收藏代碼
  1. declare  
  2.     v_param1 varchar2(20):='param1';  
  3.     v_param2 varchar2(20):='param2';  
  4. begin  
  5.   up_wap(v_param1 => v_param1,v_param2 => v_param2);  
  6. end;  

 
9、  自定義函數(function)

基本語法:

Sql代碼   收藏代碼
  1. create  function  <函數名>(<參數列表,無參時忽略>)  
  2. return  <返回值類型,無長度說明>  
  3. as|is  
  4.   變量聲明、初始化  
  5. begin  
  6.   業務處理、邏輯代碼  
  7.   return  <返回的值>;  
  8.   
  9. exception  
  10.   異常捕獲、容錯處理  
  11. end  <函數名>;  

 
參數:in  入參
注:只有入參的類型。

在存儲過程和自定義函數中的參數的傳遞(入參和出參)不能使用%type或%rowtype匹配,不能使用空值null,但是存儲過程可以返回空值。

例:

Sql代碼   收藏代碼
  1. create function uf_select_name_by_id_test(v_id in number)  
  2. return varchar2  
  3. is  
  4. v_name t_test.t_name%type;  
  5. begin  
  6.   select t_name into v_name from t_test where t_id=v_id;  
  7.   return v_name;  
  8.   
  9. exception  
  10.   when others then  
  11.     dbms_output.put_line('error');  
  12. end uf_select_name_by_id_test;  
  13.   
  14.   
  15. select uf_select_name_by_id_test(1) 姓名 from dual;-- select調用  
  16.   
  17. declare --pl/sql語句塊調用  
  18.   v_name varchar2(20);  
  19. begin  
  20.   v_name:=uf_select_name_by_id_test(1);  
  21.   dbms_output.put_line('name = '||v_name);  
  22. end;  

 
10、包(package)

封裝,可以封裝過程(procedure)、函數(function)和變量。
注意,在包(package)中聲明的過程(procedure)和函數(function)必須在包的實現體(package body)中定義實現。

基本語法:

Sql代碼   收藏代碼
  1. create  package  <包名>  
  2. as|is  
  3.   變量聲明  
  4.   存儲過程聲明  
  5.   自定義函數聲明  
  6. end  <包名>;  
  7.   
  8.   
  9. create  package body <包名,與聲明部分一致>  
  10. as|is  
  11.   存儲過程的代碼實現  
  12.   自定義函數的代碼實現  
  13. end  <包名>;  

 
例:

Java代碼   收藏代碼
  1. -- 創建包upk_hello  
  2. create or replace package upk_hello  
  3. is  
  4.   v_hello_world varchar2(20):='hello world'; -- 聲明變量  
  5.   procedure up_hello_world(v_name in varchar2);-- 聲明過程  
  6.   function uf_hello_world(v_name in varchar2) return varchar2;-- 聲明函數  
  7.   
  8. end upk_hello;  
  9.   
  10.   
  11. -- 實現包(upk_hello)里聲明的方法  
  12. create or replace package body upk_hello  
  13. is  
  14.   procedure up_hello_world(v_name in varchar2)  
  15.   is  
  16.     v_string varchar2(100);  
  17.   begin  
  18.     v_string:=v_name||' say hello world!';  
  19.     dbms_output.put_line(v_string);  
  20.   exception  
  21.     when others then dbms_output.put_line('error');  
  22.   end up_hello_world;  
  23.   
  24.   function uf_hello_world(v_name in varchar2) return varchar2  
  25.   is  
  26.     v_string varchar2(100);  
  27.   begin  
  28.     v_string:=v_name||' say hello world!';  
  29.     return v_string;  
  30.   exception  
  31.     when others then dbms_output.put_line('error');  
  32.   end uf_hello_world;  
  33.   
  34. end upk_hello;  
  35.   
  36.   
  37. -- 包的調用  
  38.   
  39. declare  
  40.   v_msg varchar2(100);  
  41. begin  
  42.   upk_hello.up_hello_world('bing');  
  43.   v_msg:=upk_hello.uf_hello_world('admin');  
  44.   
  45.   dbms_output.put_line(v_msg);  
  46.   dbms_output.put_line(upk_hello.v_hello_world);  
  47.   
  48. end;  

 

存儲過程中的3種循環:
1、

Sql代碼   收藏代碼
  1. is  
  2.      i int;  
  3. begin  
  4.      i :=1;  
  5.      loop  
  6.          ..  
  7.          exit when i =10;  
  8.          i :=i+1;  
  9.      end loop;  

 
2、
   

Sql代碼   收藏代碼
  1. i :=1;  
  2.    while i<=5 loop  
  3.        ..  
  4.        i :=i+1;  
  5.    end loop;  

 
3、

Sql代碼   收藏代碼
  1. for i in 1..100 loop  
  2.      ..........  
  3.    end loop;  

 

這是我以前的學習筆記,LZ湊合着看看吧,應該能看懂一些吧
===================================================
55 java跟oracle 調用(存儲過程,函數等)
55.1 Java調用無參的函數
1:函數為:
create or replace function MyF1 return varchar2 is
  Result varchar2(20);
begin
  dbms_output.put_line('now in My F1');
  Result := 'Now MyF1 return';
  return(Result);
end MyF1;
 
2:Java程序
/**
     * 演示調用有一個沒有參數的函數
     * @throws Exception
     */
    private static void t1() throws Exception {
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection(
                "jdbc:oracle:thin:@127.0.0.1:1521:orcl", "test", "test");
        try {
            CallableStatement stmt = conn
                    .prepareCall("{?=call MyF1()}");
            stmt.registerOutParameter(1, Types.VARCHAR);
            stmt.execute();
            System.out.println(stmt.getString(1));
        } finally {
            conn.close();
        }
    }
 
 
55.2 Java調用無參但有返回值的存儲過程
1:存儲過程
create or replace procedure MyP1(str out  Varchar2) is
begin
  dbms_output.put_line('Hello Procedure.');
  str :='Haha,Hello Procedure';
end MyP1;
 
 
2:程序
/**
     * 如何調用無參但有返回值的存儲過程 測試的存儲過程
     * @throws Exception
     */
    private static void t2() throws Exception {
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection(
                "jdbc:oracle:thin:@127.0.0.1:1521:orcl", "test", "test");
        try {
            CallableStatement stmt = conn.prepareCall("{call MyP1(?)}");
            // 注意,這里的stmt.getInt(1)中的數值1並非任意的,而是和存儲過程中的out列對應的,
            // 如果out是在第一個位置,那就是 stmt.getInt(1),如果是第三個位置,就是getInt.getInt(3),
            // 當然也可以同時有多個返回值,那就是再多加幾個out 參數了。
            stmt.registerOutParameter(1, Types.VARCHAR);
            stmt.execute();
            System.out.println(stmt.getString(1));
        } finally {
            conn.close();
        }
    }
 
 
55.3 Java調用有參的(傳入)函數
1:函數
create or replace function MyF2(a number,b varchar2) return varchar2 is
  Result varchar2(50);
begin
  dbms_output.put_line('a==='||a||',b=='||b);
  Result := a||b;
  return(Result);
end MyF2;
 
2:程序
/**
     * 調用有參的函數
     * @throws Exception
     */
    private static void t3() throws Exception {
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection(
                "jdbc:oracle:thin:@127.0.0.1:1521:orcl", "test", "test");
        try {
            CallableStatement stmt = conn
                    .prepareCall("{?=call MyF2(?,?)}");
            stmt.setInt(2, 15);
            stmt.setString(3, "HelloF2");
            stmt.registerOutParameter(1, Types.VARCHAR);
            stmt.execute();
 
            System.out.println(stmt.getString(1));
        } finally {
            conn.close();
        }
    }
 
55.4 Java調用有參的(傳入傳出)存儲過程
1:存儲過程
create or replace procedure MyP2(a in number,b in varchar2,c out varchar2) is
begin
       dbms_output.put_line('a=='||a||',b=='||b); 
       c := 'ret=='||a||',b=='||b;
end MyP2;
 
2:程序
    /**
     * 調用有參數和返回值的存儲過程
     * @throws Exception
     */
    private static void t4() throws Exception {
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection(
                "jdbc:oracle:thin:@127.0.0.1:1521:orcl", "test", "test");
        try {
            CallableStatement stmt = conn.prepareCall("{call MyP2(?,?,?)}");
            stmt.setInt(1, 5);
            stmt.setString(2, "測試");
            stmt.registerOutParameter(3, Types.VARCHAR);
            stmt.execute();
 
            System.out.println(stmt.getString(3));
        } finally {
            conn.close();
        }
    }
 
 
 
55.5 Java向存儲過程傳入傳出對象的數組
1:在數據中創建對象
create or replace type UserModel as object(
 uuid varchar2(20),
name varchar2(20)
);
 
2:在數據庫中建立對象的集合類型
create or replace type userCol as table of UserModel;
 
create or replace type retUserCol as table of UserModel;
 
3:在數據庫中建立包
包頭:
create or replace package MyTestPackage is
       TYPE dbRs IS REF CURSOR;
       procedure MyP3(a1 in userCol,a2 out dbRs);
      
end MyTestPackage;
 
包體:
create or replace package body MyTestPackage is
 
  procedure MyP3(a1 in userCol,a2 out dbRs) as
            umCol retUserCol := retUserCol();
  begin
            for i in 1.. a1.count loop
                insert into tbl_test values (a1(i).uuid,a1(i).name);
            end loop;
            commit;
                 
            umCol.Extend;
            umCol(1):=UserModel('retUuid11','retName11');
            umCol.Extend;
            umCol(2):=UserModel('retUuid22','retName22');
                 
            open a2 for select * from table(cast(umCol as retUserCol));
  end;
 
begin
  null;
end MyTestPackage;
 
4:程序:
/**
     * 測試向pl/sql傳入對象集合,從pl/sql返回任意的對象的集合
     * @param list
     * @throws Exception
     */
    private static void t5(List list) throws Exception {
        CallableStatement stmt = null;
        Connection con = null;
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            con = DriverManager.getConnection(
                    "jdbc:oracle:thin:@127.0.0.1:1521:orcl", "test", "test");
            if (con != null) {
                ARRAY aArray = getArray(con, "USERMODEL", "USERCOL", list);//該函數調用的第二三個參數必須大寫
                stmt = con.prepareCall("{call MyTestPackage.MyP3(?,?)}");
                ((OracleCallableStatement) stmt).setARRAY(1, aArray);
                stmt.registerOutParameter(2, OracleTypes.CURSOR);
                stmt.execute();
                ResultSet  rs=(ResultSet)stmt.getObject(2);
               
                while(rs.next()){
                    String uuid = rs.getString("uuid");
                    String name = rs.getString("name");
                    System.out.println("the uuid="+uuid+",name="+name);
                }
               
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    private static ARRAY getArray(Connection con, String OracleObj, String Oraclelist,
            List objlist) throws Exception {
        ARRAY list = null;
        if (objlist != null && objlist.size() > 0) {
            StructDescriptor structdesc = new StructDescriptor(OracleObj, con);
            STRUCT[] structs = new STRUCT[objlist.size()];
            Object[] result = new Object[0];
            for (int i = 0; i < objlist.size(); i++) {
                result = new Object[2];//數組大小應和你定義的數據庫對象(UserModel)的屬性的個數
                result[0] = ((UserModel)(objlist.get(i))).getUuid(); //將list中元素的數據傳入result數組
                result[1] = ((UserModel)(objlist.get(i))).getName(); //
 
                structs[i] = new STRUCT(structdesc, con, result);
            }
            ArrayDescriptor desc = ArrayDescriptor.createDescriptor(Oraclelist,
                    con);
            list = new ARRAY(desc, con, structs);
        }
        return list;
    }
 
 
 
如果使用Tomcat的DBCP的連接池,需要把連接進行轉換
public Connection getNativeConnection(Connection con) throws SQLException {
        if (con instanceof DelegatingConnection) {
         Connection nativeCon = ((DelegatingConnection) con).getInnermostDelegate();
         return (nativeCon != null ? nativeCon : con.getMetaData().getConnection());
        }
        return con;
      }


==============================

Oracle中table變量在JDBC中的運用

1.先定義一個返回數組類型的方法

create or replace type my_table_type is table of varchar2(20);

create or replace function func
return my_table_type
is
i my_table_type:=my_table_type();
begin
    select name bulk collect into i from emps;
    return i;
end;


2.在JDBC中調用,如果返回的是table變量

public void SelectAgus(String sql)
    {
         OracleCallableStatement call = null;
         try
         { 
             call = (OracleCallableStatement) con.prepareCall(sql);
             //如果返回的是table則用ARRAY類型,如果返回的是OBJECT的就用STRUCT
             //第三個參數是定義table的類型名
             call.registerOutParameter(1, OracleTypes.ARRAY,"MY_TABLE_TYPE");
             call.execute();
             //獲取第一個參數(這里即返回值)
             ARRAY array = call.getARRAY(1);
             //獲取表中的元素
             Datum[] dat = array.getOracleArray();
             //遍歷依次打印
             for(Datum d : dat)
             {
                 System.out.println(new String(d.getBytes()));
             }
         }catch(Exception e)
         {
             e.printStackTrace();
         }
    }

2.如果定義的是嵌套表結構,

   如下定義:
   create or replace type all_table is object(id number,name varchar2(20));
   create or replace type emps_table_type is table of all_table;

--創建一個函數,返回類型為emps_table_type;

create or replace function funcc
return emps_table_type
is
i emps_table_type;
begin
   --把emps中的ID,NAME屬性值全部讀取到i中
   select all_table(id,name) bulk collect into i from emps;
   return i;--返回table
end;


   

public void SelectAgus(String sql)
    {
        OracleCallableStatement call = null;
        try
        {
            call = (OracleCallableStatement) con.prepareCall(sql);
            call.registerOutParameter(1, OracleTypes.ARRAY,"EMPS_TABLE_TYPE");
            call.execute();
            ARRAY array = call.getARRAY(1);
            Datum[] dat = array.getOracleArray();
            for(Datum d : dat)
            {   //獲取了行后,要獲取一行中的元素
                STRUCT struct = (STRUCT)d;
                //這里有可能會出現亂碼,所以我分別用了兩種方式獲取元素
                Datum[] d1 = struct.getOracleAttributes();
                Object[] d2 = struct.getAttributes();
                System.out.println("ID="+d2[0]+"  "+"NAME="+
                        new String(d1[1].getBytes()));
            }
           
        }catch(Exception e){
            e.printStackTrace();
        }
    }




oracle 在一個存儲過程中調用另一個返回游標的存儲過程
實際項目當中經常需要在一個存儲過程中調用另一個存儲過程返回的游標,本文列舉了兩種情況講述具體的操作方法。
第一種情況是返回的游標是某個具體的表或視圖的數據,如:

CREATE OR REPLACE PROCEDURE P_TESTA (
PRESULT OUT SYS_REFCURSOR
)
AS
BEGIN
OPEN PRESULT FOR SELECT * FROM USERS;
END P_TESTA;

其中USERS就是數據庫中一個表。在調用的時候只要聲明一個該表的ROWTYPE類型就可以了:

CREATE OR REPLACE PROCEDURE P_TESTB
AS
    VARCURSOR SYS_REFCURSOR;
    R USERS%ROWTYPE;
BEGIN
    P_TESTA(VARCURSOR);
LOOP
    FETCH VARCURSOR INTO R;
    EXIT WHEN VARCURSOR%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(R.NAME);
END LOOP;
END P_TESTB;

第二種情況,我們返回的不是表的所有的列,或許只是其中一列或兩列,如:

CREATE OR REPLACE PROCEDURE P_TESTA (
PRESULT OUT SYS_REFCURSOR
)
AS
BEGIN
OPEN PRESULT FOR SELECT ID,NAME FROM USERS;
END P_TESTA;

這里我們只返回了USERS表的ID,NAME這兩個列,那么調用的時候也必須做相應的修改:

CREATE OR REPLACE PROCEDURE P_TESTB
AS
VARCURSOR SYS_REFCURSOR;
CURSOR TMPCURSOR IS SELECT ID,NAME FROM USERS WHERE ROWNUM=1;
R TMPCURSOR%ROWTYPE;
BEGIN
P_TESTA(VARCURSOR);
LOOP
FETCH VARCURSOR INTO R;
EXIT WHEN VARCURSOR%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(R.ID);
END LOOP;
END P_TESTB;

與之前不同的是我們聲明了一個游標類型的變量TMPCURSOR ,注意TMPCURSOR 的結構必須與存儲過程P_TESTA 返回的游標結構一致,否則就會出現錯誤。同理只要保持兩個游標類型結構一致,就可以實現自由調用。



create table test(id int,name varchar(10))
insert into test select 1,'AAAA'
insert into test select 2,'BBBB'
go

create procedure sp_test1(@count int output)
as
    select @count=count(*) from test
go

create procedure sp_test2
as
begin
    declare @count int
    exec sp_test1 @count output
    select @count
end
go

exec sp_test2
go

--輸出結果
/*
2
*/

drop procedure sp_test2,sp_test1
drop table test
go


oracle procedure 和function 的區別有哪些?

procedure 可多個返回參數,也就是out類型
function就一個
就這點區別
我覺得看使用的地方,如果只要執行一段sql的語句段,兩個都行,如過想有返回值,一個的話用function,多個的話procedure。

procedure是存儲過程 相當於程序語言里面一個處理業務的方法 也可以返回值
function是方法 相當於程序語言里面返回一個值的方法 一般較簡單 可以在dml語句中用這個方法加參數增刪改查
package相當於程序里面一個接口 里面可以定義常量數組bean 多個procedure和多個function的空實現
package body相當於程序里面一個類 是對應實現接口package的


循環:
1、..
is
     i int;
begin
     i :=1;
     loop
         ..
         exit when i =10;
         i :=i+1;
     end loop;
2、
     i :=1;
     while i<=5 loop
     ..   
         i :=i+1;
     end loop;
3、
     --如果指定了reverse選項,則循環控制變量會自動減1,否則自動加1
     for j in reverse  1..10 loop
    ..
     end loop;



1.基本結構

  CREATE OR REPLACE PROCEDURE 存儲過程名字
  (
  參數1 IN NUMBER,
  參數2 IN NUMBER
  ) IS
  變量1 INTEGER :=0;
  變量2 DATE;
  BEGIN
  END 存儲過程名字

  2.SELECT INTO STATEMENT

  將select查詢的結果存入到變量中,可以同時將多個列存儲多個變量中,必須有一條
  記錄,否則拋出異常(如果沒有記錄拋出NO_DATA_FOUND)
  例子:
  BEGIN
  SELECT col1,col2 into 變量1,變量2 FROM typestruct where xxx;
  EXCEPTION
  WHEN NO_DATA_FOUND THEN
  xxxx;
  END;
  ...

  3.IF 判斷

  IF V_TEST=1 THEN
  BEGIN
  do something
  END;
  END IF;

  4.while 循環

  WHILE V_TEST=1 LOOP
  BEGIN
  XXXX
  END;
  END LOOP;

  5.變量賦值

  V_TEST := 123;

  6.用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;

  7.帶參數的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 something
  END LOOP;
  CLOSE C_USER;

  8.用pl/sql developer debug

  連接數據庫后建立一個Test WINDOW
  在窗口輸入調用SP的代碼,F9開始debug,CTRL N單步調試


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM