我尝试从 sys_refcursor 获取 bulkcollect 记录并尝试使用 forall 插入另一个 table 但它抛出一条错误消息
I tried to fetch bulkcollect records from sys_refcursor and tried to insert another table using forall but it throw an error message
--我的第一个手术
CREATE OR REPLACE PROCEDURE P1(V_SALARY NUMBER,OUTPUT_VALUE OUT SYS_REFCURSOR)
AS
BEGIN
OPEN OUTPUT_VALUE FOR
SELECT FIRST_NAME,LAST_NAME
FROM EMPLOYEES
WHERE SALARY >V_SALARY;
END;
--第二道工序
CREATE OR REPLACE PROCEDURE P2(V_SAL NUMBER)
AS
RETURN_VALUE SYS_REFCURSOR;
TYPE TTT IS RECORD(FIRST_NAME VARCHAR2(30),LAST_NAME VARCHAR2(20)) ;
I TTT;
TYPE TNAME IS TABLE OF TTT INDEX BY BINARY_INTEGER;
K TNAME;
BEGIN
P1(V_SAL,RETURN_VALUE);
FETCH RETURN_VALUE BULK COLLECT INTO K;
FORALL X IN K.FIRST..K.LAST
INSERT INTO T1 VALUES (K(X).FIRST_NAME,K(X).LAST_NAME);
CLOSE RETURN_VALUE;
END;
/
ERROR at line 12: PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND table of records
但是如果我尝试插入 for 循环那么它工作正常..当我使用 Forall(批量绑定)时它不工作
当您尝试在从另一个过程返回 collection
或 sys_refcursor
时进行批量绑定时,这看起来像是一些错误或限制。
但是,您还有许多其他选项,而不是批量绑定(使用 FORALL
循环),它们同样具有高性能。
备选方案如下:
Table准备:
Create table employees (
first_name varchar2(100),
last_name varchar2(100),
salary number
);
Insert into employees values('A','B',1000);
Insert into employees values('C','D',2000);
Insert into employees values('E','F',3000);
Create table t1 (
first_name varchar2(100),
last_name varchar2(100)
);
--Using Objects in place of records and sys_refcursor.
Create or replace type return_value is Object (
first_name varchar2(100),
last_name varchar2(100)
);
Create or replace type v_ret_val is table of return_value;
选项 1:将 P1
声明为 Function
,然后使用集合作为直接路径插入。
CREATE OR REPLACE function p1 (v_salary NUMBER)
return v_ret_val
AS
abc v_ret_val;
BEGIN
SELECT return_value(first_name,last_name)
Bulk collect into
abc
FROM employees
WHERE salary > v_salary;
Return abc;
END;
---------------
CREATE OR REPLACE PROCEDURE p2 (
v_sal NUMBER
) AS
k v_ret_val;
BEGIN
k:=p1(v_sal);
--Displaying values of collection
For i in 1..k.count
Loop
dbms_output.put_line(k(i).first_name || k(i).last_name);
End Loop;
--Direct path insert
INSERT /*+Append*/ INTO t1
Select t.first_name,t.last_name
from (table( k )) t;
COMMIT;
END;
选项 2:使用 OUT
参数将 P1
声明为 procedure
,然后使用集合作为直接路径插入。
CREATE OR REPLACE procedure p11 (
v_salary NUMBER
,output_value OUT v_ret_val
)
AS
BEGIN
SELECT return_value(first_name,last_name)
Bulk collect into
output_value
FROM employees
WHERE salary > v_salary;
END;
------------------------------
CREATE OR REPLACE PROCEDURE p2 ( v_sal NUMBER)
AS
k v_ret_val;
BEGIN
p11(v_sal,k);
For i in 1..k.count
Loop
dbms_output.put_line(k(i).first_name || k(i).last_name);
End Loop;
INSERT /*+Append*/ INTO t1
Select t.first_name,t.last_name
from (table( k )) t;
END;
选项 3:使用 OUT
参数将 P1
声明为 procedure
,然后 Merging
目标集合 Table.
CREATE OR REPLACE PROCEDURE p2 (
v_sal NUMBER
) AS
k v_ret_val;
BEGIN
p11(v_sal,k);
For i in 1..k.count
Loop
dbms_output.put_line(k(i).first_name || k(i).last_name);
End Loop;
MERGE INTO t1 tgt
Using ( Select t.first_name,
t.last_name
from table ( k ) t
) src
on (
tgt.first_name = src.first_name
and tgt.last_name = src.first_name
)
When not matched
then
insert (
tgt.first_name,
tgt.last_name
)
values (
src.first_name,
src.last_name
);
END;
执行:
Exec P2(1000);
输出:
SQL> Select * from t1;
FIRST_NAME LAST_NAME
-------------------------------------------
E F
C D
--我的第一个手术
CREATE OR REPLACE PROCEDURE P1(V_SALARY NUMBER,OUTPUT_VALUE OUT SYS_REFCURSOR)
AS
BEGIN
OPEN OUTPUT_VALUE FOR
SELECT FIRST_NAME,LAST_NAME
FROM EMPLOYEES
WHERE SALARY >V_SALARY;
END;
--第二道工序
CREATE OR REPLACE PROCEDURE P2(V_SAL NUMBER)
AS
RETURN_VALUE SYS_REFCURSOR;
TYPE TTT IS RECORD(FIRST_NAME VARCHAR2(30),LAST_NAME VARCHAR2(20)) ;
I TTT;
TYPE TNAME IS TABLE OF TTT INDEX BY BINARY_INTEGER;
K TNAME;
BEGIN
P1(V_SAL,RETURN_VALUE);
FETCH RETURN_VALUE BULK COLLECT INTO K;
FORALL X IN K.FIRST..K.LAST
INSERT INTO T1 VALUES (K(X).FIRST_NAME,K(X).LAST_NAME);
CLOSE RETURN_VALUE;
END;
/
ERROR at line 12: PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND table of records
但是如果我尝试插入 for 循环那么它工作正常..当我使用 Forall(批量绑定)时它不工作
当您尝试在从另一个过程返回 collection
或 sys_refcursor
时进行批量绑定时,这看起来像是一些错误或限制。
但是,您还有许多其他选项,而不是批量绑定(使用 FORALL
循环),它们同样具有高性能。
备选方案如下:
Table准备:
Create table employees (
first_name varchar2(100),
last_name varchar2(100),
salary number
);
Insert into employees values('A','B',1000);
Insert into employees values('C','D',2000);
Insert into employees values('E','F',3000);
Create table t1 (
first_name varchar2(100),
last_name varchar2(100)
);
--Using Objects in place of records and sys_refcursor.
Create or replace type return_value is Object (
first_name varchar2(100),
last_name varchar2(100)
);
Create or replace type v_ret_val is table of return_value;
选项 1:将 P1
声明为 Function
,然后使用集合作为直接路径插入。
CREATE OR REPLACE function p1 (v_salary NUMBER)
return v_ret_val
AS
abc v_ret_val;
BEGIN
SELECT return_value(first_name,last_name)
Bulk collect into
abc
FROM employees
WHERE salary > v_salary;
Return abc;
END;
---------------
CREATE OR REPLACE PROCEDURE p2 (
v_sal NUMBER
) AS
k v_ret_val;
BEGIN
k:=p1(v_sal);
--Displaying values of collection
For i in 1..k.count
Loop
dbms_output.put_line(k(i).first_name || k(i).last_name);
End Loop;
--Direct path insert
INSERT /*+Append*/ INTO t1
Select t.first_name,t.last_name
from (table( k )) t;
COMMIT;
END;
选项 2:使用 OUT
参数将 P1
声明为 procedure
,然后使用集合作为直接路径插入。
CREATE OR REPLACE procedure p11 (
v_salary NUMBER
,output_value OUT v_ret_val
)
AS
BEGIN
SELECT return_value(first_name,last_name)
Bulk collect into
output_value
FROM employees
WHERE salary > v_salary;
END;
------------------------------
CREATE OR REPLACE PROCEDURE p2 ( v_sal NUMBER)
AS
k v_ret_val;
BEGIN
p11(v_sal,k);
For i in 1..k.count
Loop
dbms_output.put_line(k(i).first_name || k(i).last_name);
End Loop;
INSERT /*+Append*/ INTO t1
Select t.first_name,t.last_name
from (table( k )) t;
END;
选项 3:使用 OUT
参数将 P1
声明为 procedure
,然后 Merging
目标集合 Table.
CREATE OR REPLACE PROCEDURE p2 (
v_sal NUMBER
) AS
k v_ret_val;
BEGIN
p11(v_sal,k);
For i in 1..k.count
Loop
dbms_output.put_line(k(i).first_name || k(i).last_name);
End Loop;
MERGE INTO t1 tgt
Using ( Select t.first_name,
t.last_name
from table ( k ) t
) src
on (
tgt.first_name = src.first_name
and tgt.last_name = src.first_name
)
When not matched
then
insert (
tgt.first_name,
tgt.last_name
)
values (
src.first_name,
src.last_name
);
END;
执行:
Exec P2(1000);
输出:
SQL> Select * from t1;
FIRST_NAME LAST_NAME
-------------------------------------------
E F
C D