我在为光标内的选择正确指向特定参数时遇到问题。
这是我写的:
create or replace procedure copy_data
is
ds1 varchar2(50) :='string1';
ds2 varchar2(50) :='string2';
seq1 number;
seq2 number;
BEGIN
select NEXT_ID into seq1 from UNIQUE_KEYS where TABLE_NAME='DATA1';
select NEXT_ID into seq2 from UNIQUE_KEYS where TABLE_NAME='DATA2'; -
execute immediate 'CREATE SEQUENCE data1_seq START WITH '||seq1||' INCREMENT BY 1';
execute immediate 'CREATE SEQUENCE data2_seq START WITH '||seq2||' INCREMENT BY 1 CACHE 300';
execute immediate 'CREATE TABLE DA1_IDS (OLD_ID NUMBER(10), NEW_ID NUMBER(10))';
execute immediate
'
Insert into DATA1 (ID,NAME,DESCRIPTION)
select data1_seq.nextval,:ds1,DESCRIPTION
from DATA1 where NAME=:ds2
'
USING ds1, ds2
;
execute immediate
'
DECLARE
v_oldid DATA2.ID%type;
v_newid number;
v_dsfield DATA2%rowtype;
cursor dsc1 is
select dsf.ID, data2_seq.nextval from DATA2 dsf left join DATA1 ds on dsf.DATA1_ID=ds.ID
where ds.NAME='||'string2'||';
cursor dsc2 is
select dsfid.NEW_ID,dsf.FIELD_NAME,dsf.DESCRIPTION,data1_seq.currval
from DATA2 dsf
left join DA1_IDS dsfid on dsf.ID=dsfid.OLD_ID;
begin
open dsc1;
loop
fetch dsc1 into v_oldid,v_newid;
IF dsc1%FOUND THEN
insert into DA1_IDS values (v_oldid,v_newid);
else
exit;
end if;
end loop;
close dsc1;
open dsc2;
loop
fetch dsc2 into v_dsfield;
IF dsc2%FOUND THEN
Insert into DATA2 values v_dsfield;
else
exit;
end if;
end loop;
close dsc2;
END;'
;
END;
现在,错误是“ string2”:无效的标识符。 我不知道如何告诉我的脚本那里应该有一个字符串值。
或者也许我走得太远,也许我应该扭转一切?
我在游标部分使用了动态SQL,因为它们需要使用序列,并且这些序列也是通过动态SQL创建的,因为它们都在过程内。
因此,当使用对游标中序列的引用时,我需要将其隐藏在动态SQL中以正确启动它。
但是我不知道如何在游标中的选择内传递字符串值。
请帮助。
答案 0 :(得分:1)
对于您所遇到的直接错误,您只需要在string2
文字值周围使用escpaed单引号即可;不知道为什么现在要进行串联,但这是不对的。代替
where ds.NAME='||'string2'||';
使用
where ds.NAME=''string2'';
您还可以使用绑定变量并将该文字传递进去,就像在第一个动态语句中一样。
答案 1 :(得分:0)
我知道距最初的问题已有一段时间,但回来只是总结一下它是如何完成的。经过多次迭代,在语法上进行了许多努力,脚本看起来像这样:
create or replace procedure copy_data
AUTHID CURRENT_USER
as
ds1 varchar2(50) :='new_label';
ds2 varchar2(50) :='source_label';
dsid varchar2(200);
seq1 number;
seq2 number;
BEGIN
execute immediate 'CREATE TABLE DSID (DSID NUMBER(10))';
dsid := 'insert into DSID (DSID) select ID from DATA1 where NAME= :ds';
execute immediate dsid USING ds2;
select NEXT_ID into seq1 from UNIQUE_KEYS where TABLE_NAME='DATA1';
select NEXT_ID into seq2 from UNIQUE_KEYS where TABLE_NAME='DATA2';
execute immediate 'CREATE SEQUENCE data1_seq START WITH '||seq1||' INCREMENT BY 1';
execute immediate 'CREATE SEQUENCE data2_seq START WITH '||seq2||' INCREMENT BY 1 CACHE 300';
execute immediate 'CREATE TABLE DA1_IDS (OLD_ID NUMBER(10), NEW_ID NUMBER(10))';
execute immediate
'Insert into DATA1 (ID,NAME,DESCRIPTION,...)
select data1_seq.nextval,:ds1,DESCRIPTION,...
from DATA1 where NAME=:ds2' USING ds1, ds2;
execute immediate
'insert into DA1_IDS (OLD_ID, NEW_ID)
select dsf.ID, data2_seq.nextval from DATA2 dsf inner join DSID ds on dsf.DS_ID=ds.DSID';
execute immediate '
DECLARE
v_dsfield DATA2%rowtype;
cursor dsfields2 is
select dsfid.NEW_ID,dsf.FIELD_NAME,dsf.DESCRIPTION,...,data1_seq.currval,...
from DATA2 dsf
inner join DA1_IDS dsfid on dsf.ID=dsfid.OLD_ID
where dsfid.NEW_ID is not NULL;
begin
open dsfields2;
loop
fetch dsfields2 into v_dsfield;
EXIT WHEN dsfields2%NOTFOUND OR dsfields2%NOTFOUND IS NULL;
if dsfields2%ROWCOUNT > 0 THEN
Insert into DATA2 values v_dsfield;
end if;
end loop;
close dsfields2;
END;'
;
实际上,它有10个类似地构造的游标,它们都在所有相关表中传播相同键对象的相同ID,并且可以附加更多相关表以类似方式动态填充具有相同相关ID的< / p>
当我开始它时,该主题的一般想法自动在我脑海中浮现出来,这很不错,因为它可以作为一段漂亮的代码,例如带有循环(游标)的pl / sql过程,所以我也可以学习或练习一些东西。 在接下来的一个月中,我编写了一个脚本,执行了完全相同的操作,但是使用了普通的sql,没有任何游标,循环,甚至序列,只是对表的简单插入:)
但是,尽管如此,我写的内容还是在客户方面得到了很好的使用,效果很好。所以我将“漂亮”版本粘贴为闭包:)