How can i get value from sql using dbms_sql type of CURSOR ....COL_TYPE=102
DECLARE
RUN_S CLOB;
IGNORE NUMBER;
SOURCE_CURSOR NUMBER;
PWFIELD_COUNT NUMBER DEFAULT 0;
L_DESCTBL DBMS_SQL.DESC_TAB2;
Z_NUMBER NUMBER;
BEGIN
RUN_S := ' SELECT 1 AS VAL1,
2 AS VAL2,
CURSOR (SELECT 11 AS VAL11,
12 AS VAL12
FROM DUAL) AS CUR1,
CURSOR (SELECT 11 AS VAL11,
12 AS VAL12
FROM DUAL) AS CUR2
FROM DUAL';
SOURCE_CURSOR := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(SOURCE_CURSOR, RUN_S, DBMS_SQL.NATIVE);
DBMS_SQL.DESCRIBE_COLUMNS2(SOURCE_CURSOR, PWFIELD_COUNT, L_DESCTBL); -- get record structure
FOR I IN 1 .. PWFIELD_COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Col ' || I || ' Type:' || L_DESCTBL(I).COL_TYPE);
IF L_DESCTBL(I).COL_TYPE = 2 THEN
DBMS_SQL.DEFINE_COLUMN(SOURCE_CURSOR, I, Z_NUMBER);
elsiF L_DESCTBL(I).COL_TYPE = 102 THEN
-- ?????
-- DBMS_SQL.DEFINE_COLUMN(SOURCE_CURSOR, I, Z_NUMBER);
null;
END IF;
NULL;
END LOOP;
IGNORE := DBMS_SQL.EXECUTE(SOURCE_CURSOR);
LOOP
IF DBMS_SQL.FETCH_ROWS(SOURCE_CURSOR) > 0 THEN
FOR I IN 1 .. PWFIELD_COUNT LOOP
IF L_DESCTBL(I).COL_TYPE IN (2) THEN
DBMS_SQL.COLUMN_VALUE(SOURCE_CURSOR, I, Z_NUMBER);
DBMS_OUTPUT.PUT_LINE('Col ' || I || ' Value:' || Z_NUMBER);
END IF;
END LOOP;
ELSE
EXIT;
END IF;
END LOOP;
END;
/
So you have a cursor expression in a dynamic SQL statement. And you want to fetch the values from this?
Sadly DBMS_SQL doesn't support this.
As a workaround, you could:
- Convert the DBMS_SQL cursor to a ref cursor (to_refcursor)
- Use standard PL/SQL looping and fetching to extract the values
For example:
DECLARE
RUN_S CLOB;
IGNORE NUMBER;
SOURCE_CURSOR NUMBER;
cur sys_refcursor;
v1 integer;
v2 integer;
c1 sys_refcursor;
c2 sys_refcursor;
c1v1 integer;
c1v2 integer;
BEGIN
RUN_S := ' SELECT 1 AS VAL1,
2 AS VAL2,
CURSOR (SELECT 11 AS VAL11,
12 AS VAL12
FROM DUAL) AS CUR1,
CURSOR (SELECT 11 AS VAL11,
12 AS VAL12
FROM DUAL) AS CUR2
FROM DUAL';
SOURCE_CURSOR := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(SOURCE_CURSOR, RUN_S, DBMS_SQL.NATIVE);
IGNORE := DBMS_SQL.EXECUTE(SOURCE_CURSOR);
cur := dbms_sql.to_refcursor(SOURCE_CURSOR);
loop
fetch cur into v1, v2, c1, c2;
exit when cur%notfound;
loop
fetch c1 into c1v1, c1v2;
exit when c1%notfound;
dbms_output.put_line('C1V1: ' || c1v1 || ' C1V2: ' || c1v2);
end loop;
end loop;
close cur;
end;
/
C1V1: 11 C1V2: 12
Or, if you're feeling brave and like playing with XML, you can pass the cursor into an XMLtype. Then process the results as XML:
DECLARE
RUN_S CLOB;
IGNORE NUMBER;
SOURCE_CURSOR NUMBER;
PWFIELD_COUNT NUMBER DEFAULT 0;
L_DESCTBL DBMS_SQL.DESC_TAB2;
Z_NUMBER NUMBER;
xdoc XMLTYPE;
BEGIN
RUN_S := ' SELECT 1 AS VAL1,
2 AS VAL2,
XMLTYPE( CURSOR (SELECT 11 AS VAL11,
12 AS VAL12
FROM DUAL)
) AS CUR1,
XMLTYPE ( CURSOR (SELECT 11 AS VAL11,
12 AS VAL12
FROM DUAL)
) AS CUR2
FROM DUAL';
SOURCE_CURSOR := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(SOURCE_CURSOR, RUN_S, DBMS_SQL.NATIVE);
DBMS_SQL.DESCRIBE_COLUMNS2(SOURCE_CURSOR, PWFIELD_COUNT, L_DESCTBL); -- get record structure
FOR I IN 1 .. PWFIELD_COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Col ' || I || ' Type:' || L_DESCTBL(I).COL_TYPE);
IF L_DESCTBL(I).COL_TYPE = 2 THEN
DBMS_SQL.DEFINE_COLUMN(SOURCE_CURSOR, I, Z_NUMBER);
elsiF L_DESCTBL(I).COL_TYPE = 109 THEN
DBMS_SQL.DEFINE_COLUMN(SOURCE_CURSOR, I, xdoc);
null;
END IF;
NULL;
END LOOP;
IGNORE := DBMS_SQL.EXECUTE(SOURCE_CURSOR);
LOOP
IF DBMS_SQL.FETCH_ROWS(SOURCE_CURSOR) > 0 THEN
FOR I IN 1 .. PWFIELD_COUNT LOOP
IF L_DESCTBL(I).COL_TYPE IN (2) THEN
DBMS_SQL.COLUMN_VALUE(SOURCE_CURSOR, I, Z_NUMBER);
DBMS_OUTPUT.PUT_LINE('Col ' || I || ' Value:' || Z_NUMBER);
ELSIF L_DESCTBL(I).COL_TYPE IN (109) THEN
DBMS_SQL.COLUMN_VALUE(SOURCE_CURSOR, I, xdoc);
DBMS_OUTPUT.PUT_LINE('Col ' || I || ' Value:' || xdoc.getStringVal);
END IF;
END LOOP;
ELSE
EXIT;
END IF;
END LOOP;
END;
/
Col 1 Type:2
Col 2 Type:2
Col 3 Type:109
Col 4 Type:109
Col 1 Value:1
Col 2 Value:2
Col 3 Value:<?xml version="1.0"?>
<ROWSET>
<ROW>
<VAL11>11</VAL11>
<VAL12>12</VAL12>
</ROW>
</ROWSET>
Col 4 Value:<?xml version="1.0"?>
<ROWSET>
<ROW>
<VAL11>11</VAL11>
<VAL12>12</VAL12>
</ROW>
</ROWSET>