FOR LOOP
は必要ありません 、1つのUPDATEだけで機能します:
UPDATE emp
SET comm = extra
WHERE comm IS NULL AND extra IS NOT NULL;
デモは次のとおりです: http://www.sqlfiddle.com/#!4/ aacc3 / 1
---編集----
気づかなかったのですが、期待される出力では、deptno10が20に更新されてdeptno
が更新されました。 別のクエリが必要です:
UPDATE emp
SET deptno = 20
WHERE deptno = 10;
----編集-----
変更された値を他のテーブルに挿入する場合は、RETURNING..BULK COLLECTおよびFORALLを使用した手順を試してください:
CREATE OR REPLACE PROCEDURE pro_cedure( p_dept_id number )
IS
TYPE changed_table_type IS TABLE OF changed%ROWTYPE;
changed_buff changed_table_type;
BEGIN
SELECT deptno, comm, extra BULK COLLECT INTO changed_buff
FROM emp
WHERE comm IS NULL AND extra IS NOT NULL AND deptno = p_dept_id
FOR UPDATE;
UPDATE emp
SET comm = extra
WHERE comm IS NULL AND extra IS NOT NULL AND deptno = p_dept_id;
FORALL i IN 1 .. changed_buff.count
INSERT INTO changed VALUES changed_buff( i );
END;
/
1回の呼び出しで膨大な数のレコード(1000を超える...または最大で数千)を処理しない場合は、この手順が機能するはずです。 1つのdept_id
の場合 1万以上の行を含めることができる場合、大量のPGAメモリを消費するため、この手順は遅くなる可能性があります。このような場合、一括収集をチャンクで行う別のアプローチが必要です。
-編集---シーケンス値の保存方法-------
テーブルがchanged
と思います 次のように4つの列があります:
CREATE TABLE "TEST"."CHANGED"
( "DEPTNO" NUMBER,
"OLDVAL" NUMBER,
"NEWVAL" NUMBER,
"SEQ_NEXTVAL" NUMBER
) ;
シーケンス値をseq_nextval
に保存します 列。
このような場合、手順は次のようになります。
create or replace
PROCEDURE pro_cedure( p_dept_id number )
IS
TYPE changed_table_type IS TABLE OF changed%ROWTYPE;
changed_buff changed_table_type;
BEGIN
SELECT deptno, comm, extra, sequence_name.nextval
BULK COLLECT INTO changed_buff
FROM emp
WHERE comm IS NULL AND extra IS NOT NULL AND deptno = p_dept_id
FOR UPDATE;
UPDATE emp
SET comm = extra
WHERE comm IS NULL AND extra IS NOT NULL AND deptno = p_dept_id;
FORALL i IN 1 .. changed_buff.count
INSERT INTO changed VALUES changed_buff( i );
END;
---編集---小さなデータセット用のカーソル付きバージョン-----
はい、データの小さなセットの場合、一括収集では速度が大幅に向上することはありません。そのような場合は、for..loopを使用したプレーンカーソルで十分です。
以下に例を示します。更新と一緒にカーソルを使用する方法については、FOR UPDATE
に注意してください。 句、WHERE CURRENT OF
を使用してカーソルからフェッチされたレコードを更新する場合に必要です。 句。
今回は、シーケンス値がINSERTステートメント内で評価されます。
create or replace
PROCEDURE pro_cedure( p_dept_id number )
IS
CURSOR mycursor IS
SELECT deptno, comm, extra
FROM emp
WHERE comm IS NULL AND extra IS NOT NULL
AND deptno = p_dept_id
FOR UPDATE;
BEGIN
FOR emp_rec IN mycursor
LOOP
UPDATE emp
SET comm = extra
WHERE CURRENT OF mycursor;
INSERT INTO changed( deptno, oldval, newval, seq_nextval)
VALUES( emp_rec.deptno, emp_rec.comm,
emp_rec.extra, sequence_name.nextval );
END LOOP;
END;