Имам курсор, където трябва да получа цял куп информация за интерфейс, но една от таблиците, от които трябва да получа информация, има по един ред за всяка информация, която ми трябва в колони.
Разгледах PIVOT и в началото изглеждаше, че ще е бъркотия (особено като се има предвид, че нямам нужда от агрегат за това), но успях да го накарам да работи добре; но аз съм сериен обучаващ се, така че все пак искам да разбера дали е възможно по следния начин:
Мислех да направя това, като извлека таблица като колона: "тип таблица на (обект)", така че да имам масив от масив в моя PL/SQL код... и работи добре! Когато моята таблица със свойства имаше само един ред, но получих ORA-01427, когато имаше повече от един. Ето кратък примерен код (използвам само таблиците с идентификатори и адреси за простота, това е истински малък 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;
/