Oracle 存储过程返回结果集


Sql代码

1. Oracle 存储过程返回结果集    
2.    
3. 过程返回记录集:     
4. CREATE OR REPLACE
5. AS
6. IS REF CURSOR;    
7.       
8. PROCEDURE get (p_id NUMBER, p_rc OUT
9. END
10. /     
11.       
12. CREATE OR REPLACE
13. AS
14. PROCEDURE get (p_id NUMBER, p_rc OUT
15. IS
16.        sqlstr   VARCHAR2 (500);     
17. BEGIN
18. THEN
19. OPEN p_rc FOR
20. SELECT ID, NAME, sex, address, postcode, birthday     
21. FROM
22. ELSE
23.           sqlstr :=     
24. select id,name,sex,address,postcode,birthday     
25. from student where
26. OPEN p_rc FOR
27. END
28. END
29. END
30. /     
31.       
32. 函数返回记录集:     
33. 建立带ref cursor定义的包和包体及函数:    
34. CREATE OR REPLACE
35. package pkg_test as
36. /* 定义ref cursor类型    
37. return类型,为弱类型,允许动态sql查询,    
38.     否则为强类型,无法使用动态sql查询;     
39. */     
40. is ref cursor;     
41.        
42. --函数申明  
43. function get(intID number) return
44. end
45. /     
46.        
47. CREATE OR REPLACE
48. package body pkg_test as
49. --函数体  
50. function get(intID number) return myrctype is
51. --定义ref cursor变量 
52.       sqlstr varchar2(500);     
53. begin
54. then
55. --静态测试,直接用select语句直接返回结果 
56. open rc for select id,name,sex,address,postcode,birthday from
57. else
58. --动态sql赋值,用:w_id来申明该变量从外部获得 
59. 'select id,name,sex,address,postcode,birthday from student where id=:w_id';    
60. --动态测试,用sqlstr字符串返回结果,用using关键词传递参数 
61. open rc for
62. end
63.        
64. return
65. end
66.        
67. end
68. /    
69. 
    =================

Oracle中函数/过程返回结果集的几种方式:
    以函数return为例,存储过程只需改为out参数即可,在oracle 10g测试通过.
    (1) 返回游标:
        return的类型为:SYS_REFCURSOR
        之后在IS里面定义变量:curr SYS_REFCURSOR;
        最后在函数体中写:
         open cur for
            select ......;
         return cur;
        例:
       




CREATE 
    
  OR 
    
  REPLACE 
    
  FUNCTION 
   A_Test(
                orType  
  varchar2 
  
        ) 
  RETURN 
   SYS_REFCURSOR
         
  is 
  
               type_cur SYS_REFCURSOR;
         
  BEGIN 
  
             
  OPEN 
   type_cur  
  FOR 
  
                     
  select 
   col1,col2,col3  
  from 
   testTable ;
                   
  RETURN 
    type_cur;
         
  END 
  ; 
     (2)返回table类型的结果集:
         首先定义一个行类型:
              
   
CREATE     
  OR 
    
  REPLACE 
   TYPE "SPLIT_ARR"   
  AS 
   OBJECT(nowStr  
  varchar2 
  ( 
  18 
  )) 
         其次以此行类型定义一个表类型:
            
   
     CREATE     
  OR 
    
  REPLACE 
   TYPE "SPLIT_TAB"  
  AS 
    
  TABLE 
    
  of 
   split_arr; 
         定义函数(此函数完成字符串拆分功能):
              
   
CREATE       OR     
  REPLACE 
    
  FUNCTION 
   GetSubStr(
                      str       in 
    
  varchar2 
  ,  
  -- 
  待分割的字符串 
  
                      splitchar    in     
  varchar2 
    
  -- 
  分割标志 
  
               )
               return    split_tab
               IS   
              restStr    varchar2   (   2000 
  )  
  default 
   GetSubStr. 
  str 
  ; 
  -- 
  剩余的字符串 
  
                 thisStr    varchar2   ( 
  18 
  ); 
  -- 
  取得的当前字符串 
  
                 indexStr    int   ; 
  -- 
  临时存放分隔符在字符串中的位置 
  
                
              v split_tab :   =    split_tab();    -- 
  返回结果 
  
   
               begin   
                 dbms_output.put_line(restStr);
                    while    length(restStr)    != 
    
  0 
  
                   LOOP
                        <<   top   >> 
  
                     indexStr :   =    instr(restStr,splitchar);    -- 
  从子串中取分隔符的第一个位置 
  
   
                        if    indexStr    = 
    
  0 
    
  and 
   length(restStr)  
  != 
    
  0 
     
  then 
  -- 
  在剩余的串中找不到分隔符 
  
                              begin   
                          v.extend;
                          v(v.   count   ) :   = 
   split_arr(Reststr);
                             return    v;
                           end   ;
                        end       if 
  ;
                    
                        if    indexStr    = 
    
  1 
    
  then 
  -- 
  -第一个字符便为分隔符,此时去掉分隔符 
  
                              begin   
                             restStr :   =    substr(restStr,   2 
  );
                                goto         top 
  ;
                           end   ;
                        end       if 
  ;
                    
                        if    length(restStr)    = 
    
  0 
    
  or 
   restStr  
  is 
    
  null 
    
  then 
  
                           return    v;
                        end       if 
  ;
                   
                     v.extend;
                     thisStr :   =    substr(restStr,   1 
  ,indexStr  
  - 
    
  1 
  );  
  -- 
  取得当前的字符串 
  
                        restStr :   =    substr(restStr,indexStr  
  + 
    
  1 
  ); 
  -- 
  -取剩余的字符串 
  
   
                     v(v.   count   ) :   = 
   split_arr(thisStr);
                      END    LOOP;
                    return    v;
               end   ; 
         在PL/SQL developer中可以直接调用
             
   
cursor    strcur    is   
                            select    nowStr    from     
  Table 
  (GetSubStr( 
  ' 
  111,222,333,,, 
  ' 
  , 
  ' 
  , 
  ' 
  )); 
     (3)以管道形式输出:
          
   
create    type row_type    as    object(a    varchar2   ( 
  10 
  ), v  
  varchar2 
  ( 
  10 
  )); 
  -- 
  定义行对象 
  
              create    type table_type    as     
  table 
    
  of 
   row_type;  
  -- 
  定义表对象 
  
              create       or     
  replace 
    
  function 
   test_fun(
            a    in       varchar2   ,b    in 
    
  varchar2 
  
        )
           return    table_type pipelined
           is   
            v row_type;   --   定义v为行对象类型   
              begin   
             for    thisrow    in    (   select 
   a, b  
  from 
   mytable  
  where 
   col1 
  = 
  a  
  and 
   col2  
  = 
   b) loop
            v :   =    row_type(thisrow.a, thisrow.b);
               pipe    row (v);
             end    loop;
             return   ;
           end   ;
           select       *       from 
    
  table 
  (test_fun( 
  ' 
  123 
  ' 
  , 
  ' 
  456 
  ' 
  )); 
  
================================fetch into 显示两次
open v_cursor for  
  select 1from dual;
   
 loop
       fetch v_cursor into v_num;DBMS_OUTPUT.PUT_LINE(v_num);
      exit when v_cursor%notfound;      
     end loop;
     close v_cursor;


 

将DBMS_OUTPUT.PUT_LINE(v_num); 放到exit when v_cursor%notfound;  之后就不会显示两次了