我怎样才能" group"多行进入我的PL / SQL游标中的集合?

时间:2014-02-26 01:28:57

标签: sql oracle plsql

我有一个游标,我需要获取接口的大量信息,但是我需要从其中获取信息的一个表对于列中需要的每个信息都有一行。

我看着PIVOT,起初看起来好像很乱(特别是考虑到我不需要聚合物),但我设法让它很好地工作;但我是一个连续学习者,所以我仍然想知道是否可能这样:

我想通过将一个表作为一个列来取这样做:“类型表(对象)”所以我的PL / SQL代码中有一个数组数组......它运行正常!当我的属性表只有一行时,但是当它有多个时,我得到了ORA-01427。 这是一个简短的示例代码(为简单起见,我仅使用ID和地址表,这是我为测试此功能而创建的实际小PL):

CREATE OR REPLACE TYPE CAIB_FIELDS AS OBJECT (
ID_QUALIFIER  VARCHAR2(3),
ID_NUMBER     VARCHAR2(20)
)
/
CREATE TYPE CAIB_TBL AS TABLE OF CAIB_FIELDS
/

DECLARE
CURSOR MYCUR(CID IN VARCHAR2) IS
SELECT CUST_ID,CUST_ADDR,UPD_DATE
(SELECT CAIB_TBL(CAIB_FIELDS(ID_QUALIFIER,ID_NUMBER)) FROM CUSTOMER_IDS B
  WHERE B.CUST_ID = A.CUST_ID
  AND   B.CUST_ADDR = A.CUST_ADDR) CAIB
FROM CUSTOMER_ADDR A
WHERE A.CUST_ID = CID
;
   TYPE MYCUR_TYPE IS TABLE OF MYCUR%ROWTYPE;
    REC_MYCUR MYCUR_TYPE;
BEGIN
    OPEN MYCUR('918888'); --This customer has only one ID row -> OK! IT WORKS!
    --For customer ID '002632', he has several ID ROWS -> ERROR ORA-01427
    LOOP
        FETCH MYCUR BULK COLLECT INTO REC_MYCUR LIMIT 100;
        FOR I IN 1..REC_MYCUR.COUNT
        LOOP
            DBMS_OUTPUT.PUT_LINE(REC_MYCUR(I).CAIB(1).ID_QUALIFIER);
            --DBMS_OUTPUT.PUT_LINE(REC_MYCUR(I).CAIB(2).ID_QUALIFIER); --this would be OK if Oracle would allow me to fetch multiple rows on my CAIB_TBL type, of course I'll just loop here if it works, but for the sake of this test, I just used fixed values..
        END LOOP;
        EXIT WHEN MYCUR%NOTFOUND;
    END LOOP;
END;

提前致谢!!

---编辑,tbone的答案正是我所寻找的,但它没有反映确切的情况,因为它只处理单个列表;对于多列,解决方案稍有变化,这是我的最终测试:

create table testA
(
col1 number,
col2 varchar2(50)
);

create table testB
(
col1 number,
col2 varchar2(50),
col3 varchar2(50)
);

insert into testA values (1,'A');
insert into testA values (2,'B');
insert into testA values (3,'C');

insert into testB values (1,'X','x');
insert into testB values (1,'Y','y');
insert into testB values (1,'Z','z');

insert into testB values (2,'BA','ba');
insert into testB values (2,'BB','bb');
commit;


CREATE OR REPLACE TYPE t_test_rec AS object
(col2 varchar2(50),
col3 varchar2(50)
)
/
create or replace type t_vchar_tab as table of t_test_rec;

DECLARE
CURSOR MYCUR IS
SELECT A.COL1, 
CAST(MULTISET(SELECT B.COL2,B.COL3 FROM TESTB B WHERE B.COL1 = A.COL1 ORDER BY B.COL2) AS T_VCHAR_TAB) AS TESTB_VALS
FROM TESTA A
;
   TYPE MYCUR_TYPE IS TABLE OF MYCUR%ROWTYPE;
    REC_MYCUR MYCUR_TYPE;
BEGIN
    OPEN MYCUR;
    LOOP
        FETCH MYCUR BULK COLLECT INTO REC_MYCUR LIMIT 100;
        FOR I IN 1..REC_MYCUR.COUNT
        LOOP
            IF REC_MYCUR(I).TESTB_VALS.COUNT = 0 THEN
                DBMS_OUTPUT.PUT_LINE(REC_MYCUR(I).COL1 || '->(NULL)');
            ELSE
                FOR J IN 1..REC_MYCUR(I).TESTB_VALS.COUNT
                LOOP
                   DBMS_OUTPUT.PUT_LINE(REC_MYCUR(I).COL1 || '->' || REC_MYCUR(I).TESTB_VALS(J).COL2 || ',' || REC_MYCUR(I).TESTB_VALS(J).COL3);
                   NULL;
                END LOOP;
            END IF;
        END LOOP;
        EXIT WHEN MYCUR%NOTFOUND;
    END LOOP;
END;
/

1 个答案:

答案 0 :(得分:4)

它有点不清楚你想要实现什么,但基于标题(将多行分组到光标的集合中),你可以这样做:

set echo on;
set display on;
set linesize 200;

create table testA
(
col1 number,
col2 varchar2(50)
);

create table testB
(
col1 number,
col2 varchar2(50)
);

create or replace type t_vchar_tab as table of varchar2(50);

insert into testA values (1,'A');
insert into testA values (2,'B');

insert into testB values (1,'X');
insert into testB values (1,'Y');
insert into testB values (1,'Z');
commit;

-- select all related testB.col2 values in a nested table for each testA.col1 value
select a.col1, 
cast(multiset(select b.col2 from testB b where b.col1 = a.col1 order by b.col2) as t_vchar_tab) as testB_vals
from testA a;

因此输出将只是tableA中的2行,但是有一个嵌套的表列,其中包含tableB中所有匹配的行