如何解决如何从函数游标返回行并在Oracle中循环
我想使用一个函数/包在oracle中运行动态查询,该函数/包将返回我可以循环的行。
create or replace FUNCTION FUNC_CHECK_table
(
I_SERVICE_ID IN NUMBER,I_COMMS_MATRIX_ID IN NUMBER,I_SRC_SOCT1 IN NUMBER,I_SRC_EOCT1 IN NUMBER,I_SRC_SOCT2 IN NUMBER,I_SRC_EOCT2 IN NUMBER,I_SRC_SOCT3 IN NUMBER,I_SRC_EOCT3 IN NUMBER,I_SRC_SOCT4 IN NUMBER,I_SRC_EOCT4 IN NUMBER,I_SRC_SECZONE IN VARCHAR2,I_SRC_NETZONE IN VARCHAR2,I_SRC_LOCZONE IN VARCHAR2,I_DST_SOCT1 IN NUMBER,I_DST_EOCT1 IN NUMBER,I_DST_SOCT2 IN NUMBER,I_DST_EOCT2 IN NUMBER,I_DST_SOCT3 IN NUMBER,I_DST_EOCT3 IN NUMBER,I_DST_SOCT4 IN NUMBER,I_DST_EOCT4 IN NUMBER,I_DST_SECZONE IN VARCHAR2,I_DST_NETZONE IN VARCHAR2,I_DST_LOCZONE IN VARCHAR2,I_PROTOCOL IN VARCHAR2,I_PORTS IN VARCHAR2,I_SERVICE_GLOBAL IN NUMBER DEFAULT 0
) RETURN SYS_REFCURSOR
IS
l_return SYS_REFCURSOR;
BEGIN
CASE I_SERVICE_GLOBAL
WHEN '0'
THEN
OPEN l_return FOR
SELECT
t1.service_id,NVL(t1.SERVICE,'All') SERVICE,t1.comms_matrix_id,t2.table_id,t2.id AS POLICY_ID,t2.action,t1.summary table_name,t1.updated_by,t2.soct1_1,t2.soct1_2,t2.soct2_1,t2.soct2_2,t2.soct3_1,t2.soct3_2,t2.soct4_1,t2.soct4_2,t2.s_seczone,t2.s_netzone,t2.s_loczone,t2.doct1_1,t2.doct1_2,t2.doct2_1,t2.doct2_2,t2.doct3_1,t2.doct3_2,t2.doct4_1,t2.doct4_2,t2.d_seczone,t2.d_netzone,t2.d_loczone,t2.protocol,t2.ports,NVL(TO_CHAR(t1.expiry_date),'Forever') EXPIRY_DATE,NVL(t2.note,'Not specified') NOTE,t2.approved_by,NVL(
(
SELECT 'yes'
FROM (
SELECT disTINCT s1.protocol_id,s1.ports
FROM ccp.fw_service_objects s1
WHERE (s1.type = 'Service')
START WITH s1.name = 'Blacklisted Ports'
CONNECT BY PRIOR id = s1.parent_id
) s1
INNER JOIN ccp.sys_list_protocols s2 ON (s1.protocol_id = s2.id)
WHERE (s2.name = t4.name)
AND (s1.ports = t2.ports)
AND (ROWNUM <= 1)
),'no') BLACKLIST,t2.approved_date,t2.seq,CASE WHEN service_id = '0' and comms_matrix_id = '0' THEN '2'
WHEN service_id != '0' and comms_matrix_id = '0' THEN '1'
WHEN service_id != '0' and comms_matrix_id != '0' THEN '0'
END table_authority
FROM CCP.v_tables_group t1
INNER JOIN CCP.v_table_policies t2 ON (t1.id = t2.table_id)
LEFT JOIN CCP.sys_list_protocols t4 ON (t2.protocol_id = t4.id)
WHERE ((t1.service_id = I_SERVICE_ID) OR (t1.service_id IS NULL) OR (t1.service_id = 0 ) )
AND ((t1.comms_matrix_id = I_COMMS_MATRIX_ID) OR (t1.comms_matrix_id IS NULL) OR t1.comms_matrix_id = 0)
AND (t1.status = 'Processed')
AND (t2.rejected_date IS NULL)
AND ((t1.expiry_date IS NULL) OR (t1.expiry_date >= SYSTIMESTAMP))
AND (
(
((I_SRC_SOCT1 >= t2.soct1_1) AND (I_SRC_EOCT1 <= t2.soct1_2))
AND ((I_SRC_SOCT2 >= t2.soct2_1) AND (I_SRC_EOCT2 <= t2.soct2_2))
AND ((I_SRC_SOCT3 >= t2.soct3_1) AND (I_SRC_EOCT3 <= t2.soct3_2))
AND ((I_SRC_SOCT4 >= t2.soct4_1) AND (I_SRC_EOCT4 <= t2.soct4_2))
)
OR (
((I_SRC_SECZONE = t2.s_seczone) OR ( (lower(t2.s_seczone) = 'any' ) )) -- AND (t2.s_netzone IS NULL) AND (t2.s_loczone IS NULL) ) )
AND ((I_SRC_NETZONE = t2.s_netzone) OR (t2.s_netzone IS NULL))
AND ((I_SRC_LOCZONE = t2.s_loczone) AND (t2.s_netzone IS NOT NULL) OR (t2.s_loczone IS NULL))
AND (t2.table_type_src = 'zone')
)
)
AND (
(
((I_DST_SOCT1 >= t2.doct1_1) AND (I_DST_EOCT1 <= t2.doct1_2))
AND ((I_DST_SOCT2 >= t2.doct2_1) AND (I_DST_EOCT2 <= t2.doct2_2))
AND ((I_DST_SOCT3 >= t2.doct3_1) AND (I_DST_EOCT3 <= t2.doct3_2))
AND ((I_DST_SOCT4 >= t2.doct4_1) AND (I_DST_EOCT4 <= t2.doct4_2))
)
OR (
((I_DST_SECZONE = t2.d_seczone) OR ( (lower(t2.d_seczone) = 'any' ) )) -- AND (t2.d_netzone IS NULL) AND (t2.d_loczone IS NULL) ) )
AND ((I_DST_NETZONE = t2.d_netzone) OR (t2.d_netzone IS NULL))
AND ((I_DST_LOCZONE = t2.d_loczone) AND (t2.d_netzone IS NOT NULL) OR (t2.d_loczone IS NULL))
AND (t2.table_type_dst = 'zone')
)
)
AND (
((t2.protocol = I_PROTOCOL) AND ( (t2.ports = I_PORTS) OR (t2.ports IS NULL) OR (lower(t2.ports) = 'any') ) )
OR
((t2.protocol = 'ICMP') AND ( (t2.ports = I_PORTS) OR (t2.ports IS NULL) OR (t2.ports = 'All') ) )
)
ORDER BY CASE WHEN service_id = '0' and comms_matrix_id = '0' THEN '2'
WHEN service_id != '0' and comms_matrix_id = '0' THEN '1'
WHEN service_id != '0' and comms_matrix_id != '0' THEN '0'
END asc,t2.approved_date desc,t2.seq
FETCH FirsT 1 ROWS ONLY;
WHEN '1' THEN
OPEN l_return FOR
SELECT
t1.service_id,NVL(
(
SELECT 'yes'
FROM (
SELECT disTINCT s1.protocol_id,s1.ports
FROM ccp.fw_service_objects s1
WHERE (s1.type = 'Service')
START WITH s1.name = 'Blacklisted Ports'
CONNECT BY PRIOR id = s1.parent_id
) s1
INNER JOIN ccp.sys_list_protocols s2 ON (s1.protocol_id = s2.id)
WHERE (s2.name = t4.name)
AND (s1.ports = t2.ports)
AND (ROWNUM <= 1)
),CASE WHEN service_id = '0' THEN '2'
WHEN service_id != '0' THEN '1'
END table_authority
FROM CCP.v_tables_service_global t1
INNER JOIN CCP.v_table_policies t2 ON (t1.id = t2.table_id)
LEFT JOIN CCP.sys_list_protocols t4 ON (t2.protocol_id = t4.id)
WHERE ((t1.service_id = I_SERVICE_ID) OR (t1.service_id IS NULL) OR (t1.service_id = 0 ) )
AND (t1.status = 'Processed')
AND (t2.rejected_date IS NULL)
AND ((t1.expiry_date IS NULL) OR (t1.expiry_date >= SYSTIMESTAMP))
AND (
(
((I_SRC_SOCT1 >= t2.soct1_1) AND (I_SRC_EOCT1 <= t2.soct1_2))
AND ((I_SRC_SOCT2 >= t2.soct2_1) AND (I_SRC_EOCT2 <= t2.soct2_2))
AND ((I_SRC_SOCT3 >= t2.soct3_1) AND (I_SRC_EOCT3 <= t2.soct3_2))
AND ((I_SRC_SOCT4 >= t2.soct4_1) AND (I_SRC_EOCT4 <= t2.soct4_2))
)
OR (
((I_SRC_SECZONE = t2.s_seczone) OR ( (lower(t2.s_seczone) = 'any' ) )) -- AND (t2.s_netzone IS NULL) AND (t2.s_loczone IS NULL) ) )
AND ((I_SRC_NETZONE = t2.s_netzone) OR (t2.s_netzone IS NULL))
AND ((I_SRC_LOCZONE = t2.s_loczone) AND (t2.s_netzone IS NOT NULL) OR (t2.s_loczone IS NULL))
AND (t2.table_type_src = 'zone')
)
)
AND (
(
((I_DST_SOCT1 >= t2.doct1_1) AND (I_DST_EOCT1 <= t2.doct1_2))
AND ((I_DST_SOCT2 >= t2.doct2_1) AND (I_DST_EOCT2 <= t2.doct2_2))
AND ((I_DST_SOCT3 >= t2.doct3_1) AND (I_DST_EOCT3 <= t2.doct3_2))
AND ((I_DST_SOCT4 >= t2.doct4_1) AND (I_DST_EOCT4 <= t2.doct4_2))
)
OR (
((I_DST_SECZONE = t2.d_seczone) OR ( (lower(t2.d_seczone) = 'any' ) )) -- AND (t2.d_netzone IS NULL) AND (t2.d_loczone IS NULL) ) )
AND ((I_DST_NETZONE = t2.d_netzone) OR (t2.d_netzone IS NULL))
AND ((I_DST_LOCZONE = t2.d_loczone) AND (t2.d_netzone IS NOT NULL) OR (t2.d_loczone IS NULL))
AND (t2.table_type_dst = 'zone')
)
)
AND (
((t2.protocol = I_PROTOCOL) AND ( (t2.ports = I_PORTS) OR (t2.ports IS NULL) OR (lower(t2.ports) = 'any') ) )
OR
((t2.protocol = 'ICMP') AND ( (t2.ports = I_PORTS) OR (t2.ports IS NULL) OR (t2.ports = 'All') ) )
)
ORDER BY CASE
WHEN service_id = '0' THEN '2'
WHEN service_id != '0' THEN '1'
END asc,t2.seq
FETCH FirsT 1 ROWS ONLY;
END CASE;
RETURN l_return;
END FUNC_CHECK_table;
我在做包裹
DECLARE
l_tables SYS_REFCURSOR;
l_table VARCHAR2 (32767);
v_emp_id employee.emp_id%type;
BEGIN
DBMS_OUTPUT.put_line ('I_SERVICE_GLOBAL: ' || I_SERVICE_GLOBAL);
l_tables := CCP.FUNC_CHECK_table (I_SERVICE_ID,I_COMMS_MATRIX_ID,I_SRC_SOCT1,I_SRC_EOCT1,I_SRC_SOCT2,I_SRC_EOCT2,I_SRC_SOCT3,I_SRC_EOCT3,I_SRC_SOCT4,I_SRC_EOCT4,I_SRC_SECZONE,I_SRC_NETZONE,I_SRC_LOCZONE,I_DST_SOCT1,I_DST_EOCT1,I_DST_SOCT2,I_DST_EOCT2,I_DST_SOCT3,I_DST_EOCT3,I_DST_SOCT4,I_DST_EOCT4,I_DST_SECZONE,I_DST_NETZONE,I_DST_LOCZONE,I_PROTOCOL,I_PORTS,I_SERVICE_GLOBAL);
LOOP
FETCH l_tables INTO l_table;
DBMS_OUTPUT.put_line ('l_table: ' || l_table);
EXIT WHEN l_tables%NOTFOUND;
END LOOP;
CLOSE l_tables;
--FOR flow_row IN flow_cursor LOOP
/*O_table_ID := tables.table_ID;
O_POLICY_ID := tables.POLICY_ID;
O_ACTION := tables.ACTION;
O_SERVICE := tables.SERVICE;
O_table_NAME := tables.table_NAME;
O_EXPIRY_DATE := tables.EXPIRY_DATE;
O_NOTE := tables.NOTE;
O_APPROVED_BY := tables.APPROVED_BY;
O_BLACKLIST := tables.BLACKLIST;
IF O_ACTION = 'deny' THEN
O_SPA := 'Prevention';
O_SPN := 'Prevention #' || tables.table_ID || '.' || tables.POLICY_ID || ' - Prevented by ' || tables.APPROVED_BY || ' until ' || tables.EXPIRY_DATE;
O_FPA := 'Prevention';
O_FPN := 'Prevention #' || tables.table_ID || '.' || tables.POLICY_ID || ' - Prevented by ' || tables.APPROVED_BY || ' until ' || tables.EXPIRY_DATE;
END IF;
IF O_ACTION = 'permit' THEN
O_SPA := 'table';
O_SPN := 'table #' || tables.table_ID || '.' || tables.POLICY_ID || ' - Approved by ' || tables.APPROVED_BY || ' until ' || tables.EXPIRY_DATE;
O_FPA := 'table';
O_FPN := 'table #' || tables.table_ID || '.' || tables.POLICY_ID || ' - Approved by ' || tables.APPROVED_BY || ' until ' || tables.EXPIRY_DATE;
END IF;*/
END;
我知道我不应该使用SYS_REFCURSOR
,但是我不确定如何将其实现为行类型并遍历结果。
我正尝试使用https://blogs.oracle.com/oraclemagazine/working-with-cursors
中的示例我需要将最终结果存储到注释掉的变量中,以作为包...O_table_ID .. O_...
中的输出返回
更新
这是我现在拥有的,但是它不起作用。
PROCEDURE CHECK_EXEMPTION_Security (
O_ERRORCODE OUT NUMBER,O_ERRORTEXT OUT VARCHAR2,O_EXEMPTION_ID OUT NUMBER,O_POLICY_ID OUT NUMBER,O_ACTION OUT VARCHAR2,O_SERVICE OUT VARCHAR2,O_EXEMPTION_NAME OUT VARCHAR2,O_EXPIRY_DATE OUT VARCHAR2,O_NOTE OUT VARCHAR2,O_APPROVED_BY OUT VARCHAR2,O_BLACKLIST OUT VARCHAR2,O_SPA OUT VARCHAR2,O_SPN OUT VARCHAR2,O_FPA OUT VARCHAR2,O_FPN OUT VARCHAR2,I_SERVICE_ID IN NUMBER,I_SERVICE_GLOBAL IN NUMBER DEFAULT 0
)
AS
BEGIN
O_EXEMPTION_ID := 0;
O_POLICY_ID := 0;
O_ACTION := '';
O_SERVICE := '';
O_EXEMPTION_NAME := '';
O_EXPIRY_DATE := '';
O_NOTE := '';
O_APPROVED_BY := '';
O_BLACKLIST := '';
O_SPA := '';
O_SPN := '';
O_FPA := '';
O_FPN := '';
DECLARE
l_exemptions SYS_REFCURSOR;
EXEMPTION l_exemptions%rOWTYPE;
BEGIN
DBMS_OUTPUT.put_line ('I_SERVICE_GLOBAL: ' || I_SERVICE_GLOBAL);
l_exemptions := CCP.FUNC_CHECK_EXEMPTION (I_SERVICE_ID,I_SERVICE_GLOBAL);
DBMS_OUTPUT.put_line (l_exemptions);
/* LOOP
FETCH l_exemptions INTO l_exemption;
EXIT WHEN l_exemptions%NOTFOUND;
END LOOP;
*/
CLOSE l_exemptions;
END;
解决方法
这是一个演示如何做的例子。
首先是一个函数(是的,它返回sys_refcursor;为什么不呢?):
SQL> CREATE OR REPLACE FUNCTION f_test (par_deptno IN dept.deptno%TYPE)
2 RETURN SYS_REFCURSOR
3 IS
4 rc SYS_REFCURSOR;
5 BEGIN
6 OPEN rc FOR SELECT empno,ename
7 FROM emp
8 WHERE deptno = par_deptno;
9
10 RETURN rc;
11 END;
12 /
Function created.
测试:请注意,您必须声明变量,以获取refcursor返回的内容。当然,它们与函数的SELECT
语句中使用的列匹配。
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 l_rc SYS_REFCURSOR;
3 l_empno emp.empno%TYPE;
4 l_ename emp.ename%TYPE;
5 BEGIN
6 l_rc := f_test (10);
7
8 LOOP
9 FETCH l_rc INTO l_empno,l_ename;
10
11 EXIT WHEN l_rc%NOTFOUND;
12 DBMS_OUTPUT.put_line (l_empno || ': ' || l_ename);
13 END LOOP;
14 END;
15 /
7782: CLARK
7839: KING
7934: MILLER
PL/SQL procedure successfully completed.
SQL>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。