показва набор от резултати от съхранена процедура на oracle 10g

Използвам PL/SQL Developer и съм написал процедура за стартиране на отчет и трябва да направя процедура за извеждане на набора от резултати.

Процедурата приема входни параметри и трябва да изведе набора от резултати.

Не мога да използвам изглед, защото процедурата извиква няколко API, които приемат параметрите, които предавам на процедурата.

Разбирам от многото търсене, че е възможно да се използва ref_cursor, но не мога да накарам ti да работи.

Опростена версия на процедурата е:

CREATE OR REPLACE PROCEDURE IFSINFO.SHORTAGE_SHEET (vSite     IN VARCHAR2,
                                                    vBuyer    IN VARCHAR2,
                                                    vSupplier IN VARCHAR2,
                                                    vCursor   OUT SYS_REFCURSOR)   
AS                                                    
BEGIN
    OPEN vCursor FOR                   
        SELECT blah blah blah blah blah blah;
END;

Опитах се да изпълня процедурата и да покажа набора от резултати, използвайки:

BEGIN
    vsite       := 'S03';
    vbuyer      := 'AW';
    vsupplier   := '%';    
    vcursor     refcursor;

    IFSINFO.SHORTAGE_SHEET(vsite => :vsite,
                           vbuyer => :vbuyer,
                           vsupplier => :vsupplier,
                           vcursor => :vcursor);                           
    print vcursor;                           
END;

И също:

variable rc refcursor; 
exec IFSINFO.SHORTAGE_SHEET('S03','AW','TQ1',:rc2); 
print rc2

Но нито една работа. моля, може ли някой да ме посъветва, че съм на края на акъла си.

Благодаря ти Роб


person RobLaw84    schedule 07.12.2010    source източник
comment
Трябва да добавите етикета oracle, това не е специфично за 10g.   -  person redcayuga    schedule 07.12.2010


Отговори (4)


Има ли грешка, която виждате, когато изпълните тази процедура или я стартирате в SQLPLUS? Можете ли да публикувате вашата sqlplus сесия такава, каквато е?

PRINT е специфична за sqlplus команда и не може да бъде извикана вътре в процедурния блок. Ако трябва да отпечатате резултатите от рекурсор вътре в процедура, тогава ще трябва да извлечете от него и да отпечатате всеки запис във формата, който ви е необходим.

SQL> create or replace procedure test_REFCURSOR (
  2     i_number in number,
  3     o_cursor out sys_refcursor) 
  4  as
  5  begin
  6     open o_cursor for
  7        'select empno, ename from emp
  8             where rownum < ' || i_number ;
  9  end;
 10  /

Procedure created.

SQL> variable rc refcursor;
SQL> exec test_refcursor(5, :rc);

PL/SQL procedure successfully completed.

SQL> print rc;

     EMPNO ENAME
---------- ----------
      7369 SMITH
      7499 ALLEN
      7521 WARD
      7566 JONES

Трябва също така да промените вашата процедура (или) извикването на процедурата, за да имате различни имена на променливи. Общо взето, поставям пред всички входни променливи "i_" и всички изходни променливи с "o_". По този начин вашата декларация за процедура ще изглежда така..

CREATE OR REPLACE PROCEDURE IFSINFO.SHORTAGE_SHEET (i_Site     IN VARCHAR2,
                                                    i_Buyer    IN VARCHAR2,
                                                    i_Supplier IN VARCHAR2,
                                                    o_Cursor   OUT SYS_REFCURSOR) AS ....

и извикването на процедурата ще бъде..

IFSINFO.SHORTAGE_SHEET(    i_site     => vsite,
                           i_buyer    => vbuyer,
                           i_supplier => vsupplier,
                           o_cursor   => vcursor);

Не е необходимо да използвате ":" в началото за тези променливи, тъй като те не са променливи на средата на хоста (това е случаят с второто ви изпълнение с помощта на SQLPLUS, където използвате sqlplus променливата "rc" в извикването на процедурата)

person Rajesh Chamarthi    schedule 07.12.2010
comment
Не използвам SQL PLus, използвам PL/SQL Developer, за съжаление в този случай не мога да използвам SQL plus. - person RobLaw84; 08.12.2010
comment
няма грешка, когато го стартирам в pl/sql developer, той просто не извежда нищо. - person RobLaw84; 08.12.2010
comment
Изглежда, че настройката set serveroutput on не е включена за вашия pl/sql разработчик. Можете да поставите set serveroutput в скрипта Login.sql в директорията, където е PL/SQL Developer, и да го рестартирате, за да коригирате това. - person Rajesh Chamarthi; 08.12.2010

В основата на това в pl/sql developer кодът е както следва.

Създайте обект за съхраняване на набора от резултати

CREATE OR REPLACE TYPE ABC.TEST_TYPE
AS OBJECT
( 
  "Site"                       VARCHAR2(25),
);

Създайте тип като таблица на горния обект

CREATE OR REPLACE TYPE ABC.TEST_COL 
    AS TABLE OF ABC.TEST_TYPE

Създайте пакет за изпълнение на SQL

CREATE OR REPLACE PACKAGE ABC.TEST_RPT AS
    FUNCTION get_report(vPart     VARCHAR2,
                        vBuyer    VARCHAR2,
                        vSupplier VARCHAR2) RETURN ABC.TEST_COL 
    PIPELINED;
END;

Създайте тялото на пакета, за да изпълните SQL

CREATE OR REPLACE PACKAGE BODY ABC.TEST_RPT AS
  FUNCTION get_report(vPart     VARCHAR2,
                      vBuyer    VARCHAR2,
                      vSupplier VARCHAR2) RETURN ABC.TEST_COL 
    PIPELINED IS
    CURSOR cTest(vPart     VARCHAR2,
                 vBuyer    VARCHAR2,
                 vSupplier VARCHAR2) IS

          SELECT Site
            FROM table
           WHERE Part = vPart
             AND Buyer = vBuyer
             AND Supplier = vSupplier;



  BEGIN
    FOR part_rec IN cTest(vSite, vBuyer, vSupplier) LOOP
      PIPE ROW(ABC.TEST_TYPE(part_rec.Site));

    END LOOP;
    RETURN;
    CLOSE cTest;
  END;
END;

Кодът за изпълнение и извеждане на набора от резултати

ИЗБЕРЕТЕ * ОТ ТАБЛИЦА(ABC.TEST_RPT.get_report('','',''))

person RobLaw84    schedule 09.12.2010

Вашата референтна курсорна променлива е rc. Но след това използвате rc2.

Променете rc2 на rc и трябва да работи

person user3177508    schedule 09.01.2014

person    schedule
comment
Обърнете внимание, че публикуваното от Раджеш решение е по-просто. Командата exec създава минимален pl/sql блок, който трябва да е подходящ за този пример. - person redcayuga; 07.12.2010
comment
Не използвам SQL PLus, използвам PL/SQL Developer, за съжаление в този случай не мога да използвам SQL plus. - person RobLaw84; 08.12.2010