为什么我不能执行stmt
查询?
它显示tabb
是无效的标识符。
TYPE tab_row IS TABLE OF tab_name%ROWTYPE;
tabb tab_row;
TYPE cur_ref Is Ref Cursor;
c cur_ref;
stmt_string Varchar2(1000);
stmt Varchar2(1000);
Begin
stmt_string := 'Select * from ' || tab1 || ' mft
Where mft.mfmt_id IS NOT NULL
and mft.MFMT_FLAG IS NULL';
Open c For stmt_string;
Fetch c bulk collect into tabb;
Close c;
stmt:= 'Update '|| tab || ' m
Set m.mfmt_mat_bnr = tabb(i).mfmt_mat_bnr,
m.mfmt_mat_type = tabb(i).mfmt_mat_type,
m.mfmt_be_seg = tabb(i).mfmt_be_seg
Where m.mfmt_id = tabb(i).mfmt_id';
For i in 1..tabb.count loop
Execute Immediate stmt;
End loop;
End;
答案 0 :(得分:0)
我还没有看到tabb
被宣布在哪里。正如您在评论中提到的,它是一个集合。
从您的代码中我可以理解您正在循环遍历此集合的值。这意味着这些值是变量,即每次迭代都会改变值。因此,您需要使用它们。
你当前的动态语句,这个值是静态字符串。每次迭代时,此Set m.mfmt_mat_bnr = tabb(i).mfmt_mat_bnr,
将生成相同的字符串。因此,您需要将其更改为Set m.mfmt_mat_bnr = '|| tabb(i).mfmt_mat_bnr||', ...etc
我可以按如下方式重写您的代码:
TYPE tab_row IS TABLE OF tab_name%ROWTYPE;
tabb tab_row;
TYPE cur_ref Is Ref Cursor;
c cur_ref;
stmt_string Varchar2(1000);
stmt Varchar2(1000);
Begin
stmt_string := 'Select * from ' || tab1 || ' mft
Where mft.mfmt_id IS NOT NULL
and mft.MFMT_FLAG IS NULL';
Open c For stmt_string;
Fetch c bulk collect into tabb;
Close c;
stmt:= 'Update '|| tab || ' m
Set m.mfmt_mat_bnr = '||tabb(i).mfmt_mat_bnr||',
m.mfmt_mat_type = '||tabb(i).mfmt_mat_type||',
m.mfmt_be_seg = '||tabb(i).mfmt_be_seg||'
Where m.mfmt_id = '||tabb(i).mfmt_id;
For i in 1..tabb.count loop
Execute Immediate stmt;
End loop;
End;
由于此代码未经过测试,我强烈建议您先确认一件事。是tabb
是否在范围内正确声明。
答案 1 :(得分:0)
如果问题出在您执行语句的循环中,可以尝试使用EXECUTE IMMEDIATE .. USING
语句吗?
语法为:
EXECUTE IMMEDIATE <SQL Command>
[INTO <variable list>]
[USING <bind variable list>];
您可以尝试下面的代码,然后:
DECLARE
-- your tab1 may contain some insignificant columns with values (especially huge ones e.g. CLOB/BLOB)
-- which will extremely affect procedure's efficiency, so it's a better practice to select only those values that we need
TYPE t_tab_rec IS RECORD (
mfmt_mat_bnr tab_name.mfmt_mat_bnr%TYPE
,mfmt_mat_type tab_name.mfmt_mat_type%TYPE
,mfmt_be_seg tab_name.mfmt_be_seg%TYPE
,mfmt_id tab_name.mfmt_id%TYPE
);
TYPE t_tab_arr IS TABLE OF t_tab_rec;
tabb t_tab_arr := NEW t_tab_arr();
TYPE ref_cur IS REF CURSOR RETURN t_tab_rec; -- to assure cursor is returning t_tab_rec type records
c cur_ref;
stmt_select VARCHAR2(1000);
stmt_upadte VARCHAR2(1000);
BEGIN
stmt_select :=
'SELECT
mft.mfmt_mat_bnr
,mft.mfmt_mat_type
,mft.mfmt_be_seg
,mft.mfmt_id
FROM
'||tab1||' mft
WHERE
mft.mfmt_id IS NOT NULL
AND mft.mfmt_flag IS NOT NULL';
OPEN c FOR stmt_select;
FETCH c BULK COLLECT INTO tabb;
CLOSE c;
stmt_upadte :=
'UPDATE '||tab||'
SET mfmt_mat_bnr = :p_mfmt_mat_bnr
,mfmt_mat_type = :p_mfmt_mat_type
,mfmt_be_seg = :p_mfmt_be_seg
WHERE
mfmt_id = :p_mfmt_id';
FOR idx IN tabb.FIRST .. tabb.LAST
LOOP
EXECUTE IMMEDIATE stmt_update USING tabb(idx).mfmt_mat_bnr, tabb(idx).mfmt_mat_type, tabb(idx).mfmt_be_seg, tabb(idx).mfmt_id;
END LOOP;
END;
/