在游标声明中的动态SQL内的过程中使用字符串

时间:2018-06-20 14:47:03

标签: sql oracle dynamic cursor procedure

我在为光标内的选择正确指向特定参数时遇到问题。

这是我写的:

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中以正确启动它。

但是我不知道如何在游标中的选择内传递字符串值。

请帮助。

2 个答案:

答案 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,没有任何游标,循环,甚至序列,只是对表的简单插入:)

但是,尽管如此,我写的内容还是在客户方面得到了很好的使用,效果很好。所以我将“漂亮”版本粘贴为闭包:)