Anda tidak perlu FOR LOOP
, hanya satu UPDATE yang berhasil:
UPDATE emp
SET comm = extra
WHERE comm IS NULL AND extra IS NOT NULL;
Berikut adalah demonya:http://www.sqlfiddle.com/#!4/ aacc3/1
--- EDIT ----
Saya tidak memperhatikan, bahwa pada output yang diharapkan deptno 10 telah diperbarui menjadi 20,
untuk memperbarui deptno
kueri lain diperlukan:
UPDATE emp
SET deptno = 20
WHERE deptno = 10;
---- EDIT ------strong>
Jika Anda ingin memasukkan nilai yang diubah ke tabel lain, coba prosedur dengan RETURNING..BULK COLLECT dan 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;
/
Prosedur ini akan bekerja jika Anda tidak akan memproses sejumlah besar catatan dalam satu panggilan (lebih dari 1000 ... atau maksimum beberapa ribu). Jika satu dept_id
dapat berisi sepuluh ribu atau lebih baris, maka prosedur ini mungkin lambat, karena akan menghabiskan banyak memori PGA. Dalam kasus seperti itu, pendekatan lain dengan pengumpulan massal dalam potongan diperlukan.
-- EDIT --- cara menyimpan nilai urutan -------
Saya berasumsi bahwa tabel changed
memiliki 4 kolom, seperti ini:
CREATE TABLE "TEST"."CHANGED"
( "DEPTNO" NUMBER,
"OLDVAL" NUMBER,
"NEWVAL" NUMBER,
"SEQ_NEXTVAL" NUMBER
) ;
dan kami akan menyimpan nilai urutan di seq_nextval
kolom.
Dalam kasus seperti itu, prosedurnya mungkin terlihat seperti ini:
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;
--- EDIT --- versi dengan kursor untuk kumpulan data kecil ------strong>
Ya, untuk kumpulan data kecil pengumpulan massal tidak memberikan peningkatan kecepatan yang signifikan, dan kursor biasa dengan for..loop cukup dalam kasus seperti itu.
Berikut adalah contohnya cara menggunakan kursor bersamaan dengan update, perhatikan FOR UPDATE
klausa, diperlukan ketika kami berencana untuk memperbarui catatan yang diambil dari kursor menggunakan WHERE CURRENT OF
klausa.
Kali ini nilai urutan dievaluasi dalam pernyataan 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;