填充嵌套表中的关联数组

时间:2017-05-16 18:31:49

标签: sql oracle plsql

关于我以前的问题,Include RowId value in Nested Table

我有以下示例表:

create table data_test
(
    data_id     number,
    data_value  varchar2(100),
    batch_name  varchar2(100)
);

我已将此表用作包含rowid的参数:

create or replace package dat_pkg is

    type typ_dat_rec is record (
        data_rec    data_test%rowtype,
        data_rowid  rowid);

    type typ_dat_tst is table of typ_dat_rec index by pls_integer;

    procedure transform_dat (p_batch_name data_test.batch_name%type);

    procedure proc_test (p_dat typ_dat_tst);

end dat_pkg;
/

使用过程transform_dat,我想用l_dat_rec表中的过滤记录填充变量data_test,转换数据,最后使用{{1}更新记录过程:

proc_test

然而我收到错误create or replace package body dat_pkg is procedure transform_dat (p_batch_name data_test.batch_name%type) is cursor cur_dat is select rowid, a.* from data_test a where batch_name = p_batch_name; l_dat_rec typ_dat_tst; begin open cur_dat; fetch cur_dat BULK COLLECT into l_dat_rec; close cur_dat; -- Do the Transformation here. Example -- for i in l_dat_rec.count loop if l_dat_rec(i).data_value = 'hello' then l_dat_rec(i).data_id := l_dat_rec(i).data_id + l_dat_rec(i).data_id; else l_dat_rec(i).data_id := l_dat_rec(i).data_id * l_dat_rec(i).data_id; end if; end loop; -- update the table proc_test (p_dat => l_dat_rec); end transform_dat; procedure proc_test (p_dat typ_dat_tst) is begin for i in 1..p_dat.count loop update data_test set data_value = p_dat(i).data_value where data_id = p_dat(i).data_id and rowid = p_dat(i).data_rowid; end loop; end proc_test; end dat_pkg; / 。使用PLS-00597: expression 'L_DAT_REC' in the INTO list is of wrong type时会出现同样的错误。

我应该使用什么来填充BULK COLLECT

1 个答案:

答案 0 :(得分:1)

在上一个问题的答案中,我提到使用%rowtype字段填充集合会更难。据我所知,除非你声明一个SQL级别的对象类型而不是一个记录类型,否则你不能使用bulk collect(尽管它有值得检查,如果有的话)也许在12c中改变了。)

我相信你很难使用一个更简单的游标循环来分别构建你的类型中的两个字段(即%rowtype子字段和rowid字段),然后构建集合一次一行:

create or replace package body dat_pkg is

    procedure transform_dat (p_batch_name data_test.batch_name%type)
    is

        cursor cur_dat is
        select rowid, a.*
        from   data_test a
        where  batch_name = p_batch_name;

        l_dat_tst typ_dat_tst;
        l_rec data_test%rowtype;

    begin

        for rec_dat in cur_dat loop
            l_rec.data_id := rec_dat.data_id;
            l_rec.data_value := rec_dat.data_value;
            l_rec.batch_name := rec_dat.batch_name;
            -- or use a counter you increment for this...
            l_dat_tst(l_dat_tst.count + 1).data_rec := l_rec;
            l_dat_tst(l_dat_tst.count).data_rowid := rec_dat.rowid;
        end loop;

        -- Do the Transformation here. Example --            

        for i in 1..l_dat_tst.count loop
            if l_dat_tst(i).data_rec.data_value = 'hello' then
                l_dat_tst(i).data_rec.data_value := 'was hello';
            else            
                l_dat_tst(i).data_rec.data_value := 'was not hello';
            end if;
        end loop;

        -- update the table            
        proc_test (p_dat => l_dat_tst);

    end transform_dat;

    procedure proc_test (p_dat  typ_dat_tst)
    is
    begin

        for i in 1..p_dat.count loop

            update  data_test        
            set     data_value  = p_dat(i).data_rec.data_value  
            where   data_id     = p_dat(i).data_rec.data_id
            and     rowid       = p_dat(i).data_rowid;

        end loop;

    end proc_test;

end dat_pkg;
/    

如前所述,对子字段记录字段的引用必须合格,因此我在两个过程的引用中都插入了.data_rec。我已经更改了虚拟转换以修改值而不是ID,因为这意味着不会发生任何更新。

使用一些虚拟数据进行演示:

insert into data_test values (1, 'hello', 'test');
insert into data_test values (2, 'hello', 'test');
insert into data_test values (3, 'hello', 'exclude');
insert into data_test values (4, 'goodbye', 'test');


exec dat_pkg.transform_dat('test');

select * from data_test;

   DATA_ID DATA_VALUE           BATCH_NAME          
---------- -------------------- --------------------
         1 was hello            test                
         2 was hello            test                
         3 hello                exclude             
         4 was not hello        test