Dynamic IN-Lists
This article presents a number of methods for parameterizing the IN-list of a query.
oracle miscconfigurationintermediate
by OracleDba
15 views
This article presents a number of methods for parameterizing the IN-list of a query.
12345678910111213141516171819202122232425262728
--DROP TABLE emp PURGE;
CREATE TABLE emp (
empno NUMBER(4) CONSTRAINT pk_emp PRIMARY KEY,
ename VARCHAR2(10),
job VARCHAR2(9),
mgr NUMBER(4),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno NUMBER(2)
);
INSERT INTO emp VALUES (7369,'SMITH','CLERK',7902,to_date('17-12-1980','dd-mm-yyyy'),800,NULL,20);
INSERT INTO emp VALUES (7499,'ALLEN','SALESMAN',7698,to_date('20-2-1981','dd-mm-yyyy'),1600,300,30);
INSERT INTO emp VALUES (7521,'WARD','SALESMAN',7698,to_date('22-2-1981','dd-mm-yyyy'),1250,500,30);
INSERT INTO emp VALUES (7566,'JONES','MANAGER',7839,to_date('2-4-1981','dd-mm-yyyy'),2975,NULL,20);
INSERT INTO emp VALUES (7654,'MARTIN','SALESMAN',7698,to_date('28-9-1981','dd-mm-yyyy'),1250,1400,30);
INSERT INTO emp VALUES (7698,'BLAKE','MANAGER',7839,to_date('1-5-1981','dd-mm-yyyy'),2850,NULL,30);
INSERT INTO emp VALUES (7782,'CLARK','MANAGER',7839,to_date('9-6-1981','dd-mm-yyyy'),2450,NULL,10);
INSERT INTO emp VALUES (7788,'SCOTT','ANALYST',7566,to_date('13-JUL-87','dd-mm-rr')-85,3000,NULL,20);
INSERT INTO emp VALUES (7839,'KING','PRESIDENT',NULL,to_date('17-11-1981','dd-mm-yyyy'),5000,NULL,10);
INSERT INTO emp VALUES (7844,'TURNER','SALESMAN',7698,to_date('8-9-1981','dd-mm-yyyy'),1500,0,30);
INSERT INTO emp VALUES (7876,'ADAMS','CLERK',7788,to_date('13-JUL-87', 'dd-mm-rr')-51,1100,NULL,20);
INSERT INTO emp VALUES (7900,'JAMES','CLERK',7698,to_date('3-12-1981','dd-mm-yyyy'),950,NULL,30);
INSERT INTO emp VALUES (7902,'FORD','ANALYST',7566,to_date('3-12-1981','dd-mm-yyyy'),3000,NULL,20);
INSERT INTO emp VALUES (7934,'MILLER','CLERK',7782,to_date('23-1-1982','dd-mm-yyyy'),1300,NULL,10);
COMMIT;123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
CREATE OR REPLACE TYPE t_vc_in_list_tab AS TABLE OF VARCHAR2 (4000);
/
CREATE OR REPLACE FUNCTION vc_in_list (p_in_list IN VARCHAR2)
RETURN t_vc_in_list_tab
AS
l_tab t_vc_in_list_tab := t_vc_in_list_tab();
l_text VARCHAR2(32767) := p_in_list || ',';
l_idx NUMBER;
BEGIN
LOOP
l_idx := INSTR(l_text, ',');
EXIT WHEN NVL(l_idx, 0) = 0;
l_tab.extend;
l_tab(l_tab.last) := TRIM(SUBSTR(l_text, 1, l_idx - 1));
l_text := SUBSTR(l_text, l_idx + 1);
END LOOP;
RETURN l_tab;
END;
/
SELECT *
FROM emp
WHERE job IN (SELECT * FROM TABLE(vc_in_list('SALESMAN, MANAGER')))
ORDER BY ename;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------------------- ---------- ---------- ----------
7499 ALLEN SALESMAN 7698 20-FEB-1981 00:00:00 1600 300 30
7698 BLAKE MANAGER 7839 01-MAY-1981 00:00:00 2850 30
7782 CLARK MANAGER 7839 09-JUN-1981 00:00:00 2450 10
7566 JONES MANAGER 7839 02-APR-1981 00:00:00 2975 20
7654 MARTIN SALESMAN 7698 28-SEP-1981 00:00:00 1250 1400 30
7844 TURNER SALESMAN 7698 08-SEP-1981 00:00:00 1500 0 30
7521 WARD SALESMAN 7698 22-FEB-1981 00:00:00 1250 500 30
7 rows selected.
SQL>
CREATE OR REPLACE FUNCTION vc_in_list (p_in_list IN VARCHAR2)
RETURN t_vc_in_list_tab PIPELINED
AS
l_text VARCHAR2(32767) := p_in_list || ',';
l_idx NUMBER;
BEGIN
LOOP
l_idx := INSTR(l_text, ',');
EXIT WHEN NVL(l_idx, 0) = 0;
PIPE ROW (TRIM(SUBSTR(l_text, 1, l_idx - 1)));
l_text := SUBSTR(l_text, l_idx + 1);
END LOOP;
RETURN;
END;
/
SELECT *
FROM emp
WHERE job IN (SELECT * FROM TABLE(vc_in_list('SALESMAN, MANAGER')))
ORDER BY ename;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------------------- ---------- ---------- ----------
7499 ALLEN SALESMAN 7698 20-FEB-1981 00:00:00 1600 300 30
7698 BLAKE MANAGER 7839 01-MAY-1981 00:00:00 2850 30
7782 CLARK MANAGER 7839 09-JUN-1981 00:00:00 2450 10
7566 JONES MANAGER 7839 02-APR-1981 00:00:00 2975 20
7654 MARTIN SALESMAN 7698 28-SEP-1981 00:00:00 1250 1400 30
7844 TURNER SALESMAN 7698 08-SEP-1981 00:00:00 1500 0 30
7521 WARD SALESMAN 7698 22-FEB-1981 00:00:00 1250 500 30
7 rows selected.
SQL>
SELECT *
FROM emp
WHERE job MEMBER OF vc_in_list('SALESMAN, MANAGER')
ORDER BY ename;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------------------- ---------- ---------- ----------
7499 ALLEN SALESMAN 7698 20-FEB-1981 00:00:00 1600 300 30
7698 BLAKE MANAGER 7839 01-MAY-1981 00:00:00 2850 30
7782 CLARK MANAGER 7839 09-JUN-1981 00:00:00 2450 10
7566 JONES MANAGER 7839 02-APR-1981 00:00:00 2975 20
7654 MARTIN SALESMAN 7698 28-SEP-1981 00:00:00 1250 1400 30
7844 TURNER SALESMAN 7698 08-SEP-1981 00:00:00 1500 0 30
7521 WARD SALESMAN 7698 22-FEB-1981 00:00:00 1250 500 30
7 rows selected.
SQL>
CREATE OR REPLACE TYPE t_num_in_list_tab AS TABLE OF NUMBER(5);
/
CREATE OR REPLACE FUNCTION num_in_list (p_in_list IN VARCHAR2)
RETURN t_num_in_list_tab PIPELINED
AS
l_text VARCHAR2(32767) := p_in_list || ',';
l_idx NUMBER;
BEGIN
LOOP
l_idx := INSTR(l_text, ',');
EXIT WHEN NVL(l_idx, 0) = 0;
PIPE ROW (TO_NUMBER(TRIM(SUBSTR(l_text, 1, l_idx - 1))));
l_text := SUBSTR(l_text, l_idx + 1);
END LOOP;
RETURN;
END;
/
SELECT *
FROM emp
WHERE empno IN (SELECT * FROM TABLE(num_in_list('7499, 7698, 7782')))
ORDER BY ename;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------------------- ---------- ---------- ----------
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7698 BLAKE MANAGER 7839 01-MAY-81 2850 30
7782 CLARK MANAGER 7839 09-JUN-81 2450 10
3 rows selected.
SQL>123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
CREATE OR REPLACE CONTEXT parameter USING context_api;
CREATE OR REPLACE PACKAGE context_api AS
PROCEDURE set_parameter(p_name IN VARCHAR2,
p_value IN VARCHAR2);
END context_api;
/
SHOW ERRORS
CREATE OR REPLACE PACKAGE BODY context_api IS
PROCEDURE set_parameter (p_name IN VARCHAR2,
p_value IN VARCHAR2) IS
BEGIN
DBMS_SESSION.set_context('parameter', p_name, p_value);
END set_parameter;
END context_api;
/
SHOW ERRORS
EXEC context_api.set_parameter('variable1','value1');
SELECT SYS_CONTEXT('parameter','variable1')
FROM dual;
SYS_CONTEXT('PARAMETER','VARIABLE1')
------------------------------------
value1
1 row selected.
SQL>
CREATE OR REPLACE TYPE t_emp_row AS OBJECT (
empno NUMBER(4),
ename VARCHAR2(10),
job VARCHAR2(9),
mgr NUMBER(4),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno NUMBER(2)
);
/
CREATE OR REPLACE TYPE t_emp_tab AS TABLE OF t_emp_row;
/
CREATE OR REPLACE FUNCTION get_emp (p_in_list IN VARCHAR2)
RETURN t_emp_tab PIPELINED
AS
l_row emp%ROWTYPE;
l_cursor SYS_REFCURSOR;
l_sql VARCHAR2(32767);
l_text VARCHAR2(32767) := p_in_list || ',';
l_idx NUMBER;
l_count NUMBER := 1;
BEGIN
l_sql := 'SELECT * FROM emp WHERE job IN (';
LOOP
l_idx := INSTR(l_text, ',');
EXIT WHEN NVL(l_idx, 0) = 0;
context_api.set_parameter('job' || l_count,TRIM(SUBSTR(l_text, 1, l_idx - 1)));
l_sql := l_sql || 'SYS_CONTEXT(''parameter'', ''job' || l_count || '''),';
l_count := l_count + 1;
l_text := SUBSTR(l_text, l_idx + 1);
END LOOP;
l_sql := SUBSTR(l_sql, 1, LENGTH(l_sql) - 1) || ') ORDER BY ename';
OPEN l_cursor FOR l_sql;
LOOP
FETCH l_cursor
INTO l_row;
EXIT WHEN l_cursor%NOTFOUND;
PIPE ROW (t_emp_row(l_row.empno,
l_row.ename,
l_row.job,
l_row.mgr,
l_row.hiredate,
l_row.sal,
l_row.comm,
l_row.deptno));
END LOOP;
CLOSE l_cursor;
RETURN;
END;
/
SELECT *
FROM TABLE(get_emp('SALESMAN, MANAGER'));
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------------------- ---------- ---------- ----------
7499 ALLEN SALESMAN 7698 20-FEB-1981 00:00:00 1600 300 30
7698 BLAKE MANAGER 7839 01-MAY-1981 00:00:00 2850 30
7782 CLARK MANAGER 7839 09-JUN-1981 00:00:00 2450 10
7566 JONES MANAGER 7839 02-APR-1981 00:00:00 2975 20
7654 MARTIN SALESMAN 7698 28-SEP-1981 00:00:00 1250 1400 30
7844 TURNER SALESMAN 7698 08-SEP-1981 00:00:00 1500 0 30
7521 WARD SALESMAN 7698 22-FEB-1981 00:00:00 1250 500 30
7 rows selected.
SQL>
CREATE OR REPLACE FUNCTION get_emp (p_in_list IN VARCHAR2)
RETURN t_emp_tab PIPELINED
AS
l_row emp%ROWTYPE;
l_cursor SYS_REFCURSOR;
l_sql VARCHAR2(32767);
l_text VARCHAR2(32767) := p_in_list || ',';
l_idx NUMBER;
l_count NUMBER := 1;
BEGIN
l_sql := 'SELECT * FROM emp WHERE empno IN (';
LOOP
l_idx := INSTR(l_text, ',');
EXIT WHEN NVL(l_idx, 0) = 0;
context_api.set_parameter('empno' || l_count,TRIM(SUBSTR(l_text, 1, l_idx - 1)));
l_sql := l_sql || 'SYS_CONTEXT(''parameter'', ''empno' || l_count || '''),';
l_count := l_count + 1;
l_text := SUBSTR(l_text, l_idx + 1);
END LOOP;
l_sql := SUBSTR(l_sql, 1, LENGTH(l_sql) - 1) || ') ORDER BY ename';
OPEN l_cursor FOR l_sql;
LOOP
FETCH l_cursor
INTO l_row;
EXIT WHEN l_cursor%NOTFOUND;
PIPE ROW (t_emp_row(l_row.empno,
l_row.ename,
l_row.job,
l_row.mgr,
l_row.hiredate,
l_row.sal,
l_row.comm,
l_row.deptno));
END LOOP;
CLOSE l_cursor;
RETURN;
END;
/
SELECT *
FROM TABLE(get_emp('7499, 7698, 7782'));
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------------------- ---------- ---------- ----------
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7698 BLAKE MANAGER 7839 01-MAY-81 2850 30
7782 CLARK MANAGER 7839 09-JUN-81 2450 10
3 rows selected.
SQL>12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
CREATE GLOBAL TEMPORARY TABLE vc_in_list_data (
element VARCHAR2(4000)
);
CREATE OR REPLACE PROCEDURE setup_vc_in_list (p_in_list IN VARCHAR2) AS
l_text VARCHAR2(32767) := p_in_list || ',';
l_idx NUMBER;
l_element VARCHAR2(32767);
BEGIN
DELETE FROM vc_in_list_data;
LOOP
l_idx := INSTR(l_text, ',');
EXIT WHEN NVL(l_idx, 0) = 0;
l_element := TRIM(SUBSTR(l_text, 1, l_idx - 1));
l_text := SUBSTR(l_text, l_idx + 1);
INSERT INTO vc_in_list_data (element)
VALUES (l_element);
END LOOP;
END;
/
EXEC setup_vc_in_list('SALESMAN, MANAGER');
PL/SQL procedure successfully completed.
SELECT *
FROM emp
WHERE job IN (SELECT * FROM vc_in_list_data)
ORDER BY ename;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------------------- ---------- ---------- ----------
7499 ALLEN SALESMAN 7698 20-FEB-1981 00:00:00 1600 300 30
7698 BLAKE MANAGER 7839 01-MAY-1981 00:00:00 2850 30
7782 CLARK MANAGER 7839 09-JUN-1981 00:00:00 2450 10
7566 JONES MANAGER 7839 02-APR-1981 00:00:00 2975 20
7654 MARTIN SALESMAN 7698 28-SEP-1981 00:00:00 1250 1400 30
7844 TURNER SALESMAN 7698 08-SEP-1981 00:00:00 1500 0 30
7521 WARD SALESMAN 7698 22-FEB-1981 00:00:00 1250 500 30
7 rows selected.
SQL>
CREATE GLOBAL TEMPORARY TABLE num_in_list_data (
element NUMBER(5)
);
CREATE OR REPLACE PROCEDURE setup_num_in_list (p_in_list IN VARCHAR2) AS
l_text VARCHAR2(32767) := p_in_list || ',';
l_idx NUMBER;
l_element NUMBER(5);
BEGIN
DELETE FROM num_in_list_data;
LOOP
l_idx := INSTR(l_text, ',');
EXIT WHEN NVL(l_idx, 0) = 0;
l_element := TO_NUMBER(TRIM(SUBSTR(l_text, 1, l_idx - 1)));
l_text := SUBSTR(l_text, l_idx + 1);
INSERT INTO num_in_list_data (element)
VALUES (l_element);
END LOOP;
END;
/
EXEC setup_vc_in_list('7499, 7698, 7782');
SELECT *
FROM emp
WHERE empno IN (SELECT * FROM vc_in_list_data)
ORDER BY ename;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7698 BLAKE MANAGER 7839 01-MAY-81 2850 30
7782 CLARK MANAGER 7839 09-JUN-81 2450 10
3 rows selected.
SQL>Please to add comments
No comments yet. Be the first to comment!