这是关于Oracle PL / SQL的问题。
我有一个过程,在运行时之前不知道确切的WHERE子句:
DECLARE
CURSOR my_cursor is
SELECT ...
FROM ...
WHERE terms in (
(SELECT future_term2 FROM term_table), -- whether this element should be included is conditional
(SELECT future_term1 FROM term_table),
(SELECT present_term FROM term_table)
);
BEGIN
(the processing)
END;
/
(SELECT ... FROM term_table)查询返回的是一个4个字符的字符串。
对于解决方案,我正在考虑使用参数化游标:
DECLARE
target_terms SOME_DATATYPE;
CURSOR my_cursor (pi_terms IN SOME_DATATYPE) IS
SELECT ...
FROM ...
WHERE terms in my_cursor.pi_terms;
BEGIN
target_terms := CASE term_digit
WHEN '2' THEN (
(SELECT future_term2 FROM term_table),
(SELECT future_term1 FROM term_table),
(SELECT present_term FROM term_table)
) ELSE (
(SELECT future_term1 FROM term_table),
(SELECT present_term FROM term_table)
)
END;
FOR my_record IN my_cursor (target_terms) LOOP
(the processing)
END LOOP;
END;
/
问题是我不知道SOME_DATATYPE的数据类型是什么,也不知道Oracle是否支持这样的游标参数。如果支持,上面显示的方法是否正确构造target_terms的值?如果没有,怎么样?
希望知道的人可以提供建议。非常感谢你的帮助。
答案 0 :(得分:4)
您当然可以将参数传递给游标,就像您可以传递给函数一样 - 但只能传入IN参数。但是,PL / SQL是一种强类型语言,因此必须在编译时指定数据类型。
在我看来,您需要做的是动态构建查询然后使用
OPEN cursor FOR l_query;
其中l_query是构造的字符串。这应该让您对自己可以做的事情有所了解:
CREATE OR REPLACE PACKAGE return_id_sal
AUTHID DEFINER
IS
TYPE employee_rt IS RECORD
(
employee_id employees.employee_id%TYPE,
salary employees.salary%TYPE
);
FUNCTION allrows_by (append_to_from_in IN VARCHAR2 DEFAULT NULL)
RETURN SYS_REFCURSOR;
END return_id_sal;
/
CREATE OR REPLACE PACKAGE BODY return_id_sal
IS
FUNCTION allrows_by (append_to_from_in IN VARCHAR2 DEFAULT NULL)
RETURN SYS_REFCURSOR
IS
l_return SYS_REFCURSOR;
BEGIN
OPEN l_return FOR
'SELECT employee_id, salary FROM employees ' || append_to_from_in;
RETURN l_return;
END allrows_by;
END return_id_sal;
/
DECLARE
l_cursor SYS_REFCURSOR;
l_row return_id_sal.employee_rt;
BEGIN
l_cursor := return_id_sal.allrows_by ('WHERE department_id = 10');
LOOP
FETCH l_cursor INTO l_row;
EXIT WHEN l_cursor%NOTFOUND;
END LOOP;
END;
/
您需要使用此类代码对SQL注入采取预防措施。当然,用户永远不能将SQL文本直接传递给这样的函数!
答案 1 :(得分:0)
您也可以使用一些内置的VARRAY SQL类型,如SYS.ODCIVARCHAR2LIST
或创建自己的类型:
CREATE OR REPLACE NONEDITIONABLE TYPE VARCHARLIST
AS VARRAY(32767) OF VARCHAR2(4000);
然后您可以在光标中使用SELECT COLUMN_VALUE FROM TABLE(COLLECTION)
语句:
DECLARE
l_terms SYS.ODCIVARCHAR2LIS; --or VARCHARLIST
CURSOR my_cursor (p_terms IN SYS.ODCIVARCHAR2LIS) IS
SELECT your_column
FROM your_table
WHERE terms in (select COLUMN_VALUE from table (p_terms));
BEGIN
select term
bulk collect into l_terms
from (
select 'term1' term from dual
union all
select 'term2' term from dual
);
FOR my_record IN my_cursor (l_terms) LOOP
--process data from your cursor...
END LOOP;
END;