如何从嵌套表pl / sql中获取n个元素?

时间:2018-01-08 15:47:55

标签: oracle stored-procedures plsql nested-table

编译我的存储过程时遇到问题。

create or replace type CartLine as object (
    offeringId  OfferingIdList
    ,productLine      varchar2(50)
    ,equipment        char(1)
    ,installment       CHAR(1)
    ,cartItemProcess             varchar2(50)
    ,minimalPrice    decimal
);

create or replace type CartLineType is table of CartLine;

create or replace PROCEDURE GetOfferingRecommendation (
    cartLineList IN CartLineType,
    user IN UserType, 
    customer IN CustomerType, 
    processContext IN ProcessContextType, 
    recommendation out SYS_REFCURSOR  )
IS
    prodLine VARCHAR2(20);
    prodPrice NUMBER(5,0);
BEGIN
    FOR i IN cartLineList.FIRST .. cartLineList.LAST
    LOOP
        SELECT productLine, minimalPrice 
        INTO prodLine, prodPrice  
        FROM TABLE(cartLineList(i));
        OPEN recommendation FOR 
             SELECT CAST(REKOM_ID_SEQ.NEXTVAL AS VARCHAR(10)) 
                  ||'_'||cp.ID_REKOM_OFERTA
                  ||'_'||TO_CHAR(SYSDATE, 'yyyymmdd')  AS recommendationId 
                ,cp.ID_REKOM_OFERTA AS offeringId
                ,cp.PRIORYTET AS priority
            FROM REKOM_CROSS_PROM cp
            WHERE cp.LINIA_PROD = prodLine
            AND prodPrice BETWEEN cp.CENA_MIN AND cp.CENA_MAX
            ;
    END LOOP;
END GetOfferingRecommendation;

它没有被编译导致以下语句错误:

SELECT productLine, minimalPrice 
INTO prodLine, prodPrice
FROM TABLE(cartLineList(i));

我想在循环的每个新迭代中仅选择单个值。 有人可以帮我解决我的问题吗?

- 编辑1/9/2018 4:26 PM 根据话题: How to return result of many select statements as one custom table 我试图重建我的程序。 我为测试创建了类型:

create or replace TYPE tst AS OBJECT (
rekom_id varchar2(50)
,rekom_priorytet number(5,4)
);
/
create or replace TYPE tst_list IS TABLE OF tst;

之后,我改变了我的程序,如下所示:

CREATE OR REPLACE PROCEDURE GetOfferingRecommendation (cartLineList IN CartLineType, recommendation out SYS_REFCURSOR  )
IS
CURSOR CUR_TAB IS SELECT productLine, minimalPrice FROM TABLE(cartLineList);
v_tst tst_list;
BEGIN
FOR i IN CUR_TAB
LOOP
    EXECUTE IMMEDIATE 'SELECT tst_list(
         CAST(REKOM_ID_SEQ.NEXTVAL AS VARCHAR(10))||''_''||cp.ID_REKOM_OFERTA||''_''||TO_CHAR(SYSDATE, ''yyyymmdd'')
        ,cp.PRIORYTET)
        FROM REKOM_CROSS_PROM cp
        WHERE cp.LINIA_PROD ='||i.productLine||' AND '||i.minimalPrice||' BETWEEN cp.CENA_MIN AND cp.CENA_MAX'
        BULK COLLECT INTO v_tst;
    EXIT WHEN CUR_TAB%NOTFOUND;
    FOR REC IN 1 .. v_tst.COUNT
    LOOP
    PIPE ROW (v_tst(REC));
    END LOOP;
END LOOP;
OPEN recommendation FOR SELECT * FROM TABLE(v_tst);
END IF;
END GetOfferingRecommendation;

但由于发生错误,我无法编译:PLS-00629 你能告诉我我做错了吗?

2 个答案:

答案 0 :(得分:0)

使用简单分配而不是SELECT ... FROM TABLE(cartLineList(i));

LOOP
/* SELECT productLine, minimalPrice INTO prodLine, prodPrice FROM TABLE(cartLineList(i)); */
   productLine := cartLineList(i).productLine;
   minimalPrice := cartLineList(i).minimalPrice;
   .....
   .....
END LOOP;

答案 1 :(得分:0)

您不能使用来自集合的select语句在循环中分配变量,如下所示。

  

SELECT productLine,minimalPrice           INTO prodLine,prodPrice
          FROM TABLE(cartLineList(i));

使用循环不能在SELECT语句中逐个引用集合元素。您可以将该集合循环为

For i in 1..collection.count
loop
 ...
 ..
End loop;

Collection有许多行,当你这样做时,你会尝试将多行分配给一个变量,这是错误的。你可以做以下任何一种解释。相关的解释是内联的。

CREATE OR REPLACE PROCEDURE GETOFFERINGRECOMMENDATION (
     CARTLINELIST     IN       CARTLINETYPE,
     RECOMMENDATION   OUT      SYS_REFCURSOR)
IS
     TYPE V_PRODLINE IS TABLE OF VARCHAR2 (20)
          INDEX BY PLS_INTEGER;

     TYPE V_PRODPRICE IS TABLE OF NUMBER (5, 0)
          INDEX BY PLS_INTEGER;

     PRODLINE                      V_PRODLINE;
     PRODPRICE                     V_PRODPRICE;
BEGIN
    --Putting the collection result to another collection
     SELECT PRODUCTLINE,
            MINIMALPRICE
     BULK COLLECT INTO PRODLINE,
             PRODPRICE
       FROM TABLE (CARTLINELIST);

     -- Assuming number of elements will be same in both prodLine, prodPrice colection, loop can be iterated as below
     FOR I IN 1 .. PRODLINE.LAST
     LOOP
          OPEN RECOMMENDATION FOR
               SELECT    CAST (REKOM_ID_SEQ.NEXTVAL AS VARCHAR (10) )
                      || '_'
                      || CP.ID_REKOM_OFERTA
                      || '_'
                      || TO_CHAR (SYSDATE, 'yyyymmdd') AS RECOMMENDATIONID,
                      CP.ID_REKOM_OFERTA AS OFFERINGID,
                      CP.PRIORYTET AS PRIORITY
                 FROM REKOM_CROSS_PROM CP
                WHERE CP.LINIA_PROD = PRODLINE (I)
                      AND PRODPRICE (I) BETWEEN CP.CENA_MIN AND CP.CENA_MAX;
     END LOOP;
END GETOFFERINGRECOMMENDATION;

或者根据@krokodilko ..你可以这样做:

CREATE OR REPLACE PROCEDURE GETOFFERINGRECOMMENDATION (
     CARTLINELIST     IN       CARTLINETYPE,
     RECOMMENDATION   OUT      SYS_REFCURSOR)
IS
     PRODLINE                      VARCHAR2 (20);
     PRODPRICE                     NUMBER (5, 0);
BEGIN
     FOR I IN 1 .. CARTLINELIST.LAST
     LOOP
          --Assign the values of the collection to the variable declared.
          PRODUCTLINE := CARTLINELIST (I).PRODUCTLINE;
          MINIMALPRICE := CARTLINELIST (I).MINIMALPRICE;

          OPEN RECOMMENDATION FOR
               SELECT    CAST (REKOM_ID_SEQ.NEXTVAL AS VARCHAR (10) )
                      || '_'
                      || CP.ID_REKOM_OFERTA
                      || '_'
                      || TO_CHAR (SYSDATE, 'yyyymmdd') AS RECOMMENDATIONID,
                      CP.ID_REKOM_OFERTA AS OFFERINGID,
                      CP.PRIORYTET AS PRIORITY
                 FROM REKOM_CROSS_PROM CP
                WHERE CP.LINIA_PROD = PRODLINE
                      AND PRODPRICE BETWEEN CP.CENA_MIN AND CP.CENA_MAX;
     END LOOP;
END GETOFFERINGRECOMMENDATION;

<强>演示:

SQL> CREATE OR REPLACE TYPE CARTLINE AS OBJECT (
  2       PRODUCTLINE                   VARCHAR2 (50),
  3       MINIMALPRICE                  DECIMAL
  4  );
  5  /

Type created.

SQL> CREATE OR REPLACE TYPE CARTLINETYPE IS TABLE OF CARTLINE;
  2  /

Type created.

SQL> CREATE OR REPLACE PROCEDURE GETOFFERINGRECOMMENDATION (
  2       CARTLINELIST   IN   CARTLINETYPE)
  3  IS
  4       TYPE V_PRODLINE IS TABLE OF VARCHAR2 (20)
  5            INDEX BY PLS_INTEGER;
  6  
  7       TYPE V_PRODPRICE IS TABLE OF NUMBER (5, 0)
  8            INDEX BY PLS_INTEGER;
  9  
 10       PRODLINE                      V_PRODLINE;
 11       PRODPRICE                     V_PRODPRICE;
 12  BEGIN
 13       SELECT PRODUCTLINE,
 14              MINIMALPRICE
 15       BULK COLLECT INTO PRODLINE,
 16               PRODPRICE
 17         FROM TABLE (CARTLINELIST);
 18  
 19       FOR I IN 1 .. PRODLINE.COUNT
 20       LOOP
 21            DBMS_OUTPUT.PUT_LINE (   'Prod Line '
 22                                  || PRODLINE (I)
 23                                  || '  Prod Price '
 24                                  || PRODPRICE (I) );
 25       END LOOP;
 26  END GETOFFERINGRECOMMENDATION;
 27  /

Procedure created.

输出:

SQL> DECLARE
  2       VAR                           CARTLINETYPE := CARTLINETYPE ();
  3  BEGIN
  4       --Popuating the collection
  5       VAR.EXTEND (2);
  6       VAR (1) := CARTLINE ('TypeA', 6.0);
  7       VAR (2) := CARTLINE ('TypeB', 7.1);
  8    
  9    --Calling the procedure
 10       GETOFFERINGRECOMMENDATION (CARTLINELIST        => VAR);
 11  END;
 12  /
Prod Line TypeA  Prod Price 6
Prod Line TypeB  Prod Price 7

PL/SQL procedure successfully completed.

SQL>