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

Using string inside a procedure inside a dynamic SQL inside a cursor declaration

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

这是我写的:

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

但是我不知道如何在光标中的 select 中传递字符串值。

请帮忙

对于您遇到的直接错误,您只需要在 string2 文字值周围使用转义单引号;不知道为什么你现在有串联,但那是不对的。而不是

    where ds.NAME='||'string2'||';

使用

    where ds.NAME=''string2'';

您也可以使用绑定变量并传入该文字,就像您在第一个动态语句中所做的那样。

我知道自最初的问题以来已经有一段时间了,但回来只是总结一下它是如何完成的。经过多次迭代,多次与语法斗争,脚本看起来像这样:

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

当我开始它的时候,这个主题的总体思路自动在我脑海中出现,如果它是一段漂亮的代码会很好,比如 pl/sql 过程,带有循环(游标),所以我也可以学习或练习一些东西。 在接下来的一个月里,我写了一个脚本来做同样的事情,但是有一个简单的 sql,没有任何游标,循环,甚至没有序列,只是简单的插入到表:)

但是,我写的东西还是用了几次,效果很好,在客户方面也是如此。所以我将 "pretty" 版本粘贴为闭包:)