如何在Oracle 11g中使用游标在表中插入数据?

时间:2015-12-02 12:13:15

标签: oracle stored-procedures plsql cursor sql-insert

在这个过程中我想插入userid值不同,就像在这个select查询中我们插入所有数据一样。

T_ALLOCATIONCONFIG表的内容:

 id   userid   customerid   subbatchtypeid
---- -------- ------------ ----------------
 1    29       10003        1
 1    30       10003        1

VW_BATCH表的内容:

 batchid   batchname   subbatchtypeid   customerid   batchstatus_id
--------- ----------- ---------------- ------------ ----------------
 1         test        1                10003        1
 2         test1       1                10003        1
 3         test2       1                10003        1
 4         test3       1                10003        1
 5         test4       1                10003        1
 6         test5       1                10003        1
 7         test6       1                10003        1
 8         test7       1                10003        1
 9         test8       1                10003        1
 10        test9       1                10003        1
 11        test12      1                10003        1

我想在T_BATCHALLOCATION表格中找到这种类型的结果:

 id   batchid   customerid  userid
---- --------- ----------- --------
 1    1         10003        29
 2    2         10003        29
 3    3         10003        29
 4    4         10003        29
 5    5         10003        29
 6    6         10003        30
 7    7         10003        30
 8    8         10003        30
 9    9         10003        30
 10   10        10003        30

假设我们有来自vw_batch的10条记录,所以我想在userid = 29表格中插入5条带有userid = 30的记录和5条带有batchallocation的记录。

如何编写查询或存储过程来插入这种结果?

CREATE OR REPLACE PROCEDURE p_autoallocate_batches
AS
  BEGIN
    DECLARE
      --      v_coll_rules_id coll_rules.coll_rules_id%TYPE;
      v_customer_id t_customers.customer_id%TYPE;
      v_batchid     t_batch.batchid%TYPE;
      v_user_id     t_users.user_id%TYPE;
      c             types.cursortype;

      CURSOR c_aa IS
       SELECT b.customer_id,
              b.batchid,
              a.user_id
        FROM vw_batch b
        JOIN t_allocationconfig a
          ON a.customer_id = b.customer_id
         AND a.subbatchtypeid = b.subbatchtypeid
       WHERE b.batchstatus = 'New' AND a.isactive = 'Y';

    BEGIN
      -- Dbms_Output.Put_Line('Hello World');
      -- Insert Into Tmp (Column1) Values ('Started');

      OPEN c_aa;

      LOOP
        FETCH c_aa INTO v_customer_id, v_batchid, v_user_id;
        EXIT WHEN c_aa%NOTFOUND;

        IF (v_customer_id > 0 AND v_batchid > 0 AND v_user_id > 0) THEN
          INSERT INTO t_batchallocation (customer_id, batchid, user_id, created_by, created_date)
          VALUES (v_customer_id, v_batchid, v_user_id, 1, sysdate);

          UPDATE t_batch
          SET batchstatus_id = 2, modified_by = 1, modified_date = sysdate
          WHERE batchid = v_batchid;
        END IF;

        --Insert Into Tmp (Column1) Values ('Started123');

        COMMIT;
      END LOOP;

      CLOSE c_aa;

    END;
  END;

1 个答案:

答案 0 :(得分:3)

没有必要使用游标来执行此操作 - 您可以在两个sql语句中执行此操作(但您必须创建一个类型来保存已插入的batch_ids):

create type num_list as table of integer;

create or replace procedure p_autoallocate_batches
as
  v_batch_ids num_list;
begin
  insert into t_batchallocation (customer_id,
                                 batchid,
                                 user_id,
                                 created_by,
                                 created_date)
  select b.customer_id,
         b.batchid,
         a.user_id,
         1,
         sysdate
  from   vw_batch b
         inner join t_allocationconfig a on (a.customer_id = b.customer_id
                                             and a.subbatchtypeid = b.subbatchtypeid)
  where  b.batchstatus = 'New'
  and    a.isactive = 'Y'
  and    b.customer_id > 0
  and    b.batchid > 0
  and    a.user_id > 0
  returning batchid bulk collect into v_batch_ids;

  update t_batch
  set    batchstatus_id = 2, modified_by = 1, modified_date = sysdate
  where  batchid in (select * from table(v_batch_ids));

  commit;

end p_autoallocate_batches;
/

N.B。未经测试,因为您没有提供表格定义或样本数据

另外,我不确定我回答了你原来的问题,因为我不明白。请更改您的问题,以便在表格中提供一些示例数据以及您希望以表格格式插入的内容。

好的,按照您的问题中添加的其他信息,我认为以下内容将会执行您的操作:

with t_allocationconfig as (select 1 id, 29 userid, 10003 customerid, 1 subbatchtypeid from dual union all
                            select 1 id, 30 userid, 10003 customerid, 1 subbatchtypeid from dual),
               vw_batch as (select 1 batchid, 'test' batchname, 1 subbatchtypeid, 10003 customerid, 1 batchstatus_id from dual union all
                            select 2 batchid, 'test1' batchname, 1 subbatchtypeid, 10003 customerid, 1 batchstatus_id from dual union all
                            select 3 batchid, 'test2' batchname, 1 subbatchtypeid, 10003 customerid, 1 batchstatus_id from dual union all
                            select 4 batchid, 'test3' batchname, 1 subbatchtypeid, 10003 customerid, 1 batchstatus_id from dual union all
                            select 5 batchid, 'test4' batchname, 1 subbatchtypeid, 10003 customerid, 1 batchstatus_id from dual union all
                            select 6 batchid, 'test5' batchname, 1 subbatchtypeid, 10003 customerid, 1 batchstatus_id from dual union all
                            select 7 batchid, 'test6' batchname, 1 subbatchtypeid, 10003 customerid, 1 batchstatus_id from dual union all
                            select 8 batchid, 'test7' batchname, 1 subbatchtypeid, 10003 customerid, 1 batchstatus_id from dual union all
                            select 9 batchid, 'test8' batchname, 1 subbatchtypeid, 10003 customerid, 1 batchstatus_id from dual union all
                            select 10 batchid, 'test9' batchname, 1 subbatchtypeid, 10003 customerid, 1 batchstatus_id from dual union all
                            select 11 batchid, 'test12' batchname, 1 subbatchtypeid, 10003 customerid, 1 batchstatus_id from dual)
--end of mimicking your sample data - see SQL below:
select vb.batchid id, -- is id supposed to be derived using a sequence, perhaps?
       vb.batchid,
       vb.customerid,
       ta.userid
from   (select id,
               userid,
               customerid,
               subbatchtypeid,
               row_number() over (partition by id, customerid, subbatchtypeid order by userid) rn,
               count(*) over (partition by id, customerid, subbatchtypeid) cnt
        from   t_allocationconfig) ta
       inner join (select batchid,
                          batchname,
                          subbatchtypeid,
                          customerid,
                          batchstatus_id,
                          row_number() over (partition by customerid, subbatchtypeid order by batchid) rn,
                          count(*) over (partition by customerid, subbatchtypeid) cnt
                   from   vw_batch) vb on (ta.customerid = vb.customerid
                                           and ta.subbatchtypeid = vb.subbatchtypeid
                                           and ta.rn = ceil(vb.rn/ceil(vb.cnt/ta.cnt)));

        ID    BATCHID CUSTOMERID     USERID
---------- ---------- ---------- ----------
         1          1      10003         29
         2          2      10003         29
         3          3      10003         29
         4          4      10003         29
         5          5      10003         29
         6          6      10003         29
         7          7      10003         30
         8          8      10003         30
         9          9      10003         30
        10         10      10003         30
        11         11      10003         30

这意味着您的代码应该与以下内容类似:

-- make sure you have a global type:
create type num_list as table of integer;

create or replace procedure p_autoallocate_batches
as
  v_batch_ids num_list;
begin
  insert into t_batchallocation (customer_id,
                                 batchid,
                                 user_id,
                                 created_by,
                                 created_date)
  select vb.customerid,
         vb.batchid,
         ta.userid,
         1,
         sysdate
  from   (select id,
                 userid,
                 customerid,
                 subbatchtypeid,
                 row_number() over (partition by id, customerid, subbatchtypeid order by userid) rn,
                 count(*) over (partition by id, customerid, subbatchtypeid) cnt
          from   t_allocationconfig) ta
         inner join (select batchid,
                            batchname,
                            subbatchtypeid,
                            customerid,
                            batchstatus_id,
                            row_number() over (partition by customerid, subbatchtypeid order by batchid) rn,
                            count(*) over (partition by customerid, subbatchtypeid) cnt
                     from   vw_batch) vb on (ta.customerid = vb.customerid
                                             and ta.subbatchtypeid = vb.subbatchtypeid
                                             and ta.rn = ceil(vb.rn/ceil(vb.cnt/ta.cnt)))
  returning batchid bulk collect into v_batch_ids;

  update t_batch
  set    batchstatus_id = 2, modified_by = 1, modified_date = sysdate
  where  batchid in (select * from table(v_batch_ids));

  commit;

end p_autoallocate_batches;
/

N.B。您可能必须使用partition by和join子句来确保数据被分组并在正确的列上连接 - 我猜测了逻辑背后的原因,因为您没有说。希望您能够解构查询以查看它正在做什么,并在适当时进行修改!