我必须编写一个Oracle程序,该程序应该调用返回REF_CURSOR的Oracle函数。该函数声明为
FUNCTION "IMPACTNET"."TF_CONVERTPARA" (PARASTRING IN NVARCHAR2) RETURN SYS_REFCURSOR
AS
c SYS_REFCURSOR;
BEGIN
OPEN c FOR
SELECT SUBSTR(element, 1, INSTR(element, '|') - 1) as key,
SUBSTR(element, INSTR(element, '|') + 1, 99999) as val
FROM (
SELECT REGEXP_SUBSTR(PARASTRING, '[^;]+', 1, LEVEL) element
FROM dual
CONNECT BY LEVEL < LENGTH(REGEXP_REPLACE(PARASTRING, '[^;]+')) + 1
);
RETURN c;
END;
你可以告诉我为了从我的程序中调用函数我需要编写什么吗?我想将所有返回的值(形成一个包含两列的表)插入到一个有理数的表中。
提前谢谢!
答案 0 :(得分:3)
根据这一点应该有用(显然,我猜测表名和列名以及你试图实现的确切逻辑)
CREATE PROCEDURE some_procedure_name
AS
l_rc SYS_REFCURSOR := impactnet.tf_convertpara( <<some string>> );
l_key VARCHAR2(100);
l_val VARCHAR2(100);
BEGIN
LOOP
FETCH l_rc
INTO l_key, l_val;
EXIT WHEN l_rc%notfound;
INSERT INTO some_table( key_column, val_column )
VALUES( l_key, l_val );
END LOOP;
END;
正如奥利指出的那样,做BULK COLLECT
和FORALL
会更有效率。如果您只处理几千行(因为您的函数只是在分隔字符串中解析数据,我假设您期望返回相对较少的行),性能差异可能很小。但是,如果您正在处理更多数据,那么差异就会非常明显。根据Oracle版本和您的特定要求,您可以简化INSERT
中的FORALL
语句以插入记录,而不是单独列出记录中的每一列。
CREATE PROCEDURE some_procedure_name
AS
TYPE key_val_rec
IS RECORD(
key VARCHAR2(100),
val VARCHAR2(100)
);
TYPE key_val_coll
IS TABLE OF key_val_rec;
l_rc SYS_REFCURSOR := impactnet.tf_convertpara( <<some string>> );
l_coll key_val_coll;
BEGIN
LOOP
FETCH l_rc
BULK COLLECT INTO l_coll
LIMIT 100;
EXIT WHEN l_coll.count = 0;
FORALL i IN l_coll.FIRST .. l_coll.LAST
INSERT INTO some_table( key_column, val_column )
VALUES( l_coll(i).key, l_coll(i).val );
END LOOP;
END;