FORALL 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 - это то место, где мне нужна последовательность. Каждый раз, когда он запускается, он вставляет эти записи в одну и ту же таблицу, но последовательность должна начинаться с единицы каждый раз, поскольку это последовательность для коллекции, а не всей таблицы.... имеет смысл?
2 ответа
Как отмечали другие, возможно, последовательность - лучший метод для удовлетворения требований варианта использования.
Но чтобы строго ответить на ваш вопрос о том, как реплицировать переменную увеличивающегося счетчика с помощью оператора 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 увеличивать его один раз для каждой записи в коллекции.
Это просто
Создать последовательность
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 demo
Поэтому мне просто нужно было добавить числовой столбец к записи для коллекции.
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_Q TYPE, BIS_QQ
Затем я добавил функцию 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 COLLECT INTO 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);