如何从嵌套的tablepl/sql中获取n个元素?

How to get n element from nested table pl/sql?

我的存储过程编译有问题。

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));

我想 select 我的循环的每个新迭代都只有一个值。 有人可以帮我解决我的问题吗?

-- 编辑 2018 年 1 月 9 日 4:26 下午 按题目: 我试图重建我的程序。 我为测试创建了类型:

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 你能告诉我我做错了什么吗?

使用简单赋值代替 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;

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

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

无法在 SELECT 语句中使用循环 1 对 1 地引用集合元素。您可以循环遍历集合

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

集合有很多行,当您这样做时,您试图将许多行分配给一个变量,这是错误的。您可以执行以下任一说明。里面有相关的解释。

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>