多行功能

时间:2014-07-30 21:52:34

标签: oracle plsql

如何使用光标从函数返回多行数据?

Create or Replace function  Get_Course_details(Stud_ID number)
  return varchar2
Is

    cursor C_1 is
      select d.desc_english
        from course_details d ,course_track c , students s
       where D.COURSE_TRACK_ID = C.COURSE_TRACK_ID
         and C.COURSE_TRACK_ID = s.STUDENT_ID
         and s.student_ID=stud_ID;
    cursor C_2 is
      select count(d.desc_english)
        from course_details d ,course_track c , students s
       where D.COURSE_TRACK_ID = C.COURSE_TRACK_ID
         and C.COURSE_TRACK_ID = s.STUDENT_ID
         and s.student_ID=stud_ID;
  var_1   varchar2(1000);
  var_2 number;
Begin
  open c_2;
  fetch c_2
    into var_2;
  close c_2;
  for x in (select d.desc_english
              from course_details d ,course_track c , students s
             where D.COURSE_TRACK_ID = C.COURSE_TRACK_ID
               and C.COURSE_TRACK_ID = s.STUDENT_ID
               and s.student_ID=stud_ID)
  loop
    open c_1;
    fetch c_1
    into var_1;
    close c_1;
    return var_1;
  end loop;
end;

2 个答案:

答案 0 :(得分:0)

好的,正如Justin所指出的,你当前的功能几乎没有问题:

  1. var_2从未使用过。
  2. 您正在尝试返回多行数据,但是,该函数会在第一次迭代时将var_1返回给调用过程。
  3. 以下解决方案假设您正在尝试从返回许多行的游标中获取字符串数组。这是一个通用演示,您将为特定实例修改它。

    CREATE OR REPLACE FUNCTION string_array_from_cursor
    RETURN dbms_sql.Varchar2_Table
      IS
    
      --Obviously this could be _ANY_ select query
      CURSOR cursorToReturnManyRows IS
      SELECT o.object_name
      FROM   user_objects o
      WHERE  o.OBJECT_TYPE = 'TABLE';
    
      --This is an inbuilt index-by table (you could also use a varray,
      --  associative array or nested table)
      stringArray dbms_sql.Varchar2_Table;
    
    BEGIN
    
      --Use a FOR loop to iterate through the cursor, 
      -- at each iteration add the value as the next item in the array 
      FOR rec IN cursorToReturnManyRows LOOP
        stringArray(stringArray.count + 1) := rec.object_name;
      END LOOP;
    
      --After the loop is complete return the array
      RETURN stringArray;
    
    END;
    

    我建议你编译上面的函数,并在下面的测试窗口中运行它,看看它如何应用于你的实例。

    DECLARE
    
      stringArray dbms_sql.Varchar2_Table;
    
    BEGIN
    
      stringArray := string_array_from_cursor;
    
      dbms_output.put_line(stringArray.count);
    
      FOR i IN 1..stringArray.count LOOP
       dbms_output.put_line(stringArray(i));
      END LOOP;
    
    END;
    

答案 1 :(得分:0)

作为替代方案,您可以返回已打开的SYS_REFCURSOR并让调用者从游标中获取:

CREATE OR REPLACE FUNCTION GET_COURSE_DETAIL_CURSOR(STUD_ID NUMBER)
  RETURN SYS_REFCURSOR
IS
  C_1  SYS_REFCURSOR;
BEGIN
  OPEN C_1 FOR SELECT d.DESC_ENGLISH
                 FROM STUDENTS s 
                 INNER JOIN COURSE_TRACK c
                   ON c.COURSE_TRACK_ID = s.STUDENT_ID
                 INNER JOIN COURSE_DETAILS d
                   ON d.COURSE_TRACK_ID = c.COURSE_TRACK_ID
                 WHERE S.STUDENT_ID = STUD_ID;

  RETURN C_1;
END GET_COURSE_DETAIL_CURSOR;

当然,调用者将负责关闭光标。

(而BTW - 加入条件c.COURSE_TRACK_ID = s.STUDENT_ID似乎与后来的加入条件d.COURSE_TRACK_ID = c.COURSE_TRACK_ID相矛盾,但另一方面我不知道您的数据。它看起来很奇怪我)。

分享并享受。