FORALL批量收集 - 需要在不使用循环的情况下添加序列来插入语句?

时间:2018-05-09 13:38:45

标签: sql oracle plsql bulk-collect

所以我有一个FORALL批量集合,用于将值插入表中。

通常我会为必须填充的序列字段使用循环。例子就是这样........

seqno = seqno +1

.....然后我会为每个记录循环,它们会在插入时增加1。

SELECT bis_part, bis_part_org, bis_store, bis_bin, bis_lot, bis_qty
BULK COLLECT INTO V_STTK_CLTN 
FROM table1
WHERE bis_bin = 'DIRECT'
AND bis_store = p_org;


FORALL INDX IN 1 .. V_STTK_CLTN.COUNT 

  INSERT INTO table2
   (stl_part,
    stl_part_org,
    stl_trans,
    stl_store,
    stl_bin,
    stl_lot,
    stl_expqty,
    stl_phyqty,
    stl_rtype,
    stl_type,
    stl_line ) 
   VALUES
   (V_STTK_CLTN(INDX).bis_part,
    V_STTK_CLTN(INDX).bis_part_org,
    ctrans,
    V_STTK_CLTN(INDX).bis_store,
    V_STTK_CLTN(INDX).bis_bin,
    V_STTK_CLTN(INDX).bis_lot,
    V_STTK_CLTN(INDX).bis_qty,
    '',
    'STTK',
    'STTK',
     seqno);

我怎么能用一个集合来做这个,因为我在没有循环的情况下使用FORALL?

seqno值是我需要序列的地方。每次运行它都会将这些记录插入到同一个表中,但序列必须每次都以一个开头,因为它是集合的序列而不是整个表....有意义吗?

3 个答案:

答案 0 :(得分:1)

正如其他人提到的那样,也许序列是满足用例需求的最佳方法。

但是要严格回答有关如何使用FORALL语句复制递增计数器变量的问题,可以执行以下操作:

L_OFFSET := 0;

FORALL INDX IN 1 .. V_STTK_CLTN.COUNT 
  INSERT INTO table2
   (stl_part,
    stl_part_org,
    stl_trans,
    stl_store,
    stl_bin,
    stl_lot,
    stl_expqty,
    stl_phyqty,
    stl_rtype,
    stl_type,
    stl_line ) 
   VALUES
   (V_STTK_CLTN(INDX).bis_part,
    V_STTK_CLTN(INDX).bis_part_org,
    ctrans,
    V_STTK_CLTN(INDX).bis_store,
    V_STTK_CLTN(INDX).bis_bin,
    V_STTK_CLTN(INDX).bis_lot,
    V_STTK_CLTN(INDX).bis_qty,
    '',
    'STTK',
    'STTK',
     L_OFFSET+INDX);

通过这种方式,您可以将L_OFFSET设置为初始偏移,并让INDX为集合中的每个记录增加一次。

答案 1 :(得分:0)

很简单

创建序列

CREATE SEQUENCE seq;

假设您要插入表t

create table t(id INT, rowname VARCHAR2(20));

此块将在FORALL块中插入一些虚拟行,并将使用序列。批量收集来自SELECT查询或CURSOR

的集合,而不是您的循环
DECLARE 
    TYPE ctype 
      IS TABLE OF t%ROWTYPE; 
    ct ctype; 
BEGIN 
    SELECT seq.NEXTVAL AS id, 
           'ROW' 
           ||LEVEL     AS rowname 
    bulk   collect INTO ct 
    FROM   dual 
    CONNECT BY LEVEL <= 100; 

    forall i IN ct.first..ct.last 
      INSERT INTO t 
      VALUES ct(i); 
END; 

/ 

Db fiddle演示

答案 2 :(得分:0)

所以我只需要在集合的记录中添加一个数字列。

 TYPE STTK_RECORD IS RECORD(

BIS_PART T1.BIS_PART%TYPE  ,BIS_PART_ORG T1.BIS_PART_ORG%TYPE  ,BIS_STORE T1.BIS_STORE%TYPE  ,BIS_BIN T1.BIS_BIN%TYPE  ,BIS_LOT T1.BIS_LOT%TYPE  ,BIS_QTY T1.BIS_QTY%TYPE  ,RN NUMBER  );

然后我将row_number函数添加到我的select语句中以进行批量收集:

SELECT bis_part, bis_part_org, bis_store, bis_bin, bis_lot, bis_qty, ROW_NUMBER() OVER (PARTITION BY bis_store ORDER BY bis_bin desc) RN

BULK收集到V_STTK_CLTN;

最后我插入了新专栏:

FORALL INDX IN V_STTK_CLTN.FIRST .. V_STTK_CLTN.LAST

  INSERT INTO T2
   (stl_part,
    stl_part_org,
    stl_trans,
    stl_store,
    stl_bin,
    stl_lot,
    stl_expqty,
    stl_phyqty,
    stl_rtype,
    stl_type,
    stl_line ) 
   VALUES
   (V_STTK_CLTN(INDX).bis_part,
    V_STTK_CLTN(INDX).bis_part_org,
    ctrans,
    V_STTK_CLTN(INDX).bis_store,
    V_STTK_CLTN(INDX).bis_bin,
    V_STTK_CLTN(INDX).bis_lot,
    V_STTK_CLTN(INDX).bis_qty,
    '',
    'STTK',
    'STTK',
    V_STTK_CLTN(INDX).rn);