Bạn không cần FOR LOOP
, chỉ một CẬP NHẬT duy nhất hoạt động:
UPDATE emp
SET comm = extra
WHERE comm IS NULL AND extra IS NOT NULL;
Đây là bản trình diễn: http://www.sqlfiddle.com/#!4/ aacc3 / 1
--- CHỈNH SỬA ----
Tôi không nhận thấy rằng trong đầu ra dự kiến, deptno 10 đã được cập nhật thành 20,
cập nhật deptno
cần một truy vấn khác:
UPDATE emp
SET deptno = 20
WHERE deptno = 10;
---- CHỈNH SỬA -----
Nếu bạn muốn chèn các giá trị đã thay đổi vào bảng khác, hãy thử quy trình với RETURNING..BULK COLLECT và 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;
/
Quy trình sẽ hoạt động nếu bạn không xử lý số lượng lớn bản ghi trong một lần gọi (hơn 1000 ... hoặc tối đa là vài nghìn). Nếu một dept_id
có thể chứa mười nghìn hàng trở lên, thì quy trình này có thể chậm, vì nó sẽ tiêu tốn một lượng lớn bộ nhớ PGA. Trong trường hợp như vậy, cần có một cách tiếp cận khác với tập hợp hàng loạt theo khối.
- CHỈNH SỬA --- cách lưu trữ các giá trị trình tự -------
Tôi giả sử rằng bảng changed
có 4 cột, như thế này:
CREATE TABLE "TEST"."CHANGED"
( "DEPTNO" NUMBER,
"OLDVAL" NUMBER,
"NEWVAL" NUMBER,
"SEQ_NEXTVAL" NUMBER
) ;
và chúng tôi sẽ lưu trữ các giá trị trình tự trong seq_nextval
cột.
Trong trường hợp này, thủ tục có thể giống như sau:
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 --- phiên bản có con trỏ cho các tập dữ liệu nhỏ -----
Có, đối với các nhóm dữ liệu nhỏ, việc thu thập dữ liệu hàng loạt không làm tăng tốc độ đáng kể và con trỏ đơn giản với for..loop là đủ trong trường hợp như vậy.
Dưới đây là ví dụ cách bạn sử dụng con trỏ cùng với cập nhật, hãy lưu ý FOR UPDATE
mệnh đề này là bắt buộc khi chúng tôi dự định cập nhật bản ghi được tìm nạp từ con trỏ bằng cách sử dụng WHERE CURRENT OF
mệnh đề.
Lần này giá trị trình tự được đánh giá trong câu lệnh 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;