Create the implementation package to_doc_p containing the DESCRIBE function and FETCH_ROWS procedure for the to_doc polymorphic table function (PTF).
CREATE PACKAGE to_doc_p AS
FUNCTION describe(tab IN OUT DBMS_TF.table_t,
cols IN DBMS_TF.columns_t DEFAULT NULL)
RETURN DBMS_TF.describe_t;
PROCEDURE fetch_rows;
END to_doc_p;
Package created.
Create the package containing the DESCRIBE function and FETCH_ROWS procedure.
CREATE PACKAGE BODY to_doc_p AS
FUNCTION describe(tab IN OUT DBMS_TF.table_t,
cols IN DBMS_TF.columns_t DEFAULT NULL)
RETURN DBMS_TF.describe_t AS
BEGIN
FOR i IN 1 .. tab.column.count LOOP
CONTINUE WHEN NOT DBMS_TF.supported_type(tab.column(i).description.TYPE);
IF cols IS NULL THEN
tab.column(i).for_read := TRUE;
tab.column(i).pass_through := FALSE;
continue;
END IF;
FOR j IN 1 .. cols.count LOOP
IF (tab.column(i).description.name = cols(j)) THEN
tab.column(i).for_read := TRUE;
tab.column(i).pass_through := FALSE;
END IF;
END LOOP;
END LOOP;
RETURN DBMS_TF.describe_t(new_columns =>
DBMS_TF.columns_new_t(1 =>
DBMS_TF.column_metadata_t(name =>'DOCUMENT')));
END;
PROCEDURE fetch_rows AS
rst DBMS_TF.row_set_t;
col DBMS_TF.tab_varchar2_t;
rct PLS_INTEGER;
BEGIN
DBMS_TF.get_row_set(rst, row_count => rct);
FOR rid IN 1 .. rct LOOP
col(rid) := DBMS_TF.row_to_char(rst, rid);
END LOOP;
DBMS_TF.put_col(1, col);
END;
END to_doc_p;
Package Body created.
Create the standalone to_doc PTF.
CREATE FUNCTION to_doc(
tab TABLE,
cols columns DEFAULT NULL)
RETURN TABLE PIPELINED ROW POLYMORPHIC USING to_doc_p;
Function created.
SELECT * FROM to_doc(scott.dept)
DOCUMENT | {"DEPTNO":10, "DNAME":"ACCOUNTING", "LOC":"NEW YORK"} | {"DEPTNO":20, "DNAME":"RESEARCH", "LOC":"DALLAS"} | {"DEPTNO":30, "DNAME":"SALES", "LOC":"CHICAGO"} | {"DEPTNO":40, "DNAME":"OPERATIONS", "LOC":"BOSTON"} |
---|
For all employees in departments 10 and 30, display the DEPTNO, ENAME and DOCUMENT columns ordered by DEPTNO and ENAME.
SELECT deptno, ename, document
FROM to_doc(scott.emp, columns(empno,job,mgr,hiredate,sal,comm))
WHERE deptno IN (10, 30)
ORDER BY 1, 2
DEPTNO | ENAME | DOCUMENT | 10 | CLARK | {"EMPNO":7782, "JOB":"MANAGER", "MGR":7839, "HIREDATE":"09-JUN-81", "SAL":2450} | 10 | KING | {"EMPNO":7839, "JOB":"PRESIDENT", "HIREDATE":"17-NOV-81", "SAL":5000} | 10 | MILLER | {"EMPNO":7934, "JOB":"CLERK", "MGR":7782, "HIREDATE":"23-JAN-82", "SAL":1300} | 30 | ALLEN | {"EMPNO":7499, "JOB":"SALESMAN", "MGR":7698, "HIREDATE":"20-FEB-81", "SAL":1600, "COMM":300} | 30 | BLAKE | {"EMPNO":7698, "JOB":"MANAGER", "MGR":7839, "HIREDATE":"01-MAY-81", "SAL":2850} | 30 | JAMES | {"EMPNO":7900, "JOB":"CLERK", "MGR":7698, "HIREDATE":"03-DEC-81", "SAL":950} | 30 | MARTIN | {"EMPNO":7654, "JOB":"SALESMAN", "MGR":7698, "HIREDATE":"28-SEP-81", "SAL":1250, "COMM":1400} | 30 | TURNER | {"EMPNO":7844, "JOB":"SALESMAN", "MGR":7698, "HIREDATE":"08-SEP-81", "SAL":1500, "COMM":0} | 30 | WARD | {"EMPNO":7521, "JOB":"SALESMAN", "MGR":7698, "HIREDATE":"22-FEB-81", "SAL":1250, "COMM":500} |
---|
WITH e AS (
SELECT ename name, sal, deptno, loc
FROM scott.emp NATURAL JOIN scott.dept
WHERE job = 'CLERK')
SELECT ROWNUM doc_id, t.*
FROM to_doc(e) t
DOC_ID | DOCUMENT | 1 | {"NAME":"MILLER", "SAL":1300, "DEPTNO":10, "LOC":"NEW YORK"} | 2 | {"NAME":"SMITH", "SAL":800, "DEPTNO":20, "LOC":"DALLAS"} | 3 | {"NAME":"ADAMS", "SAL":1100, "DEPTNO":20, "LOC":"DALLAS"} | 4 | {"NAME":"JAMES", "SAL":950, "DEPTNO":30, "LOC":"CHICAGO"} |
---|
WITH t(c1,c2,c3) AS (
SELECT NULL, NULL, NULL
FROM dual
UNION ALL
SELECT 1, NULL, NULL
FROM dual
UNION ALL
SELECT NULL, 2, NULL
FROM dual
UNION ALL
SELECT 0, NULL, 3
FROM dual)
SELECT *
FROM to_doc(t)
DOCUMENT | {} | {"C1":1} | {"C2":2} | {"C1":0, "C3":3} |
---|
For all employees in department 30, display the values of the member with property names ENAME and COMM.
SELECT JSON_VALUE(document, '$.ENAME') ename,
JSON_VALUE(document, '$.COMM') comm
FROM to_doc(scott.emp)
WHERE JSON_VALUE(document, '$.DEPTNO') = 30
ENAME | COMM | BLAKE | - | ALLEN | 300 | WARD | 500 | MARTIN | 1400 | TURNER | 0 | JAMES | - |
---|