使用游标 PL SQL 匿名块的多行更新
multi row update using cursors PL SQL anonymous block
我们如何编写一个 PL SQL 块来一次更新多行。场景是,有两个表 TABLE1,TABLE2
都有一个公共列 COLUMN1
。在匿名块中,游标定义在 TABLE1
.
在 运行 第一次使用块时,即使用 v_run:=1
和 v_offset:=2
时,前两行将在光标中。在 运行 第二次访问该块 v_run:=2
时,TABLE1
的下两行将在游标中,依此类推。
示例代码中的 v_SPECIAL_VARIABLE
应该是
在第一个 运行 上,即 v_run:=1
,前两行(第 1,2 行)被提取到游标中,它们在 TABLE2
中对应的 COLUMN2
值被更新为 'N'
和 TABLE2
中的其余行更新为 'n'
.
在第二个 运行 即 v_run:=2
接下来的两行(第 3,4 行)从游标中的 TABLE1
及其对应的 COLUMN2
值中获取TABLE2
中的行更新为 'N'
,TABLE2
中的其余行更新为 'n'
.
在第三个 运行 即 v_run:=3
接下来的两行(第 5,6 行)从游标中的 TABLE1
及其对应的 COLUMN2
值中获取TABLE2
中的行更新为 'N'
,TABLE2
中的其余行更新为 'n'
.
表 1 包含
id | COLUMN1 | total
-------------------------
1 | 1256480 | 5
2 | 1256481 | 3
3 | 1256482 | 2
4 | 1256483 | 1
5 | 1256484 | 3
6 | 1256485 | 2
7 | 1256486 | 1
8 | 1256487 | 3
表 2 包含
| COLUMN1 | column2
-------------------------
| 1256480 | N
| 1256481 | N
| 1256482 | N
| 1256483 | N
| 1256484 | N
| 1256485 | n
| 1256486 | n
| 1256487 | n
示例代码
declare
v_offset number:=2;
v_run number:=1;
cursor curv1 is
select column1 from
(select rownum rowcol,column1 from table1)
where rowcol between (v_run-1)*v_offset+1 and v_offset*v_run;
begin
open curv1 ;
fetch curv1 into v_SPECIAL_VARIABLE
----- first update
update table2 set column2='N' where
column1=(' ALL the values in v_SPECIAL_VARIABLE');
----- second update
update table2 set column2='n' where
column1 not in (' ALL the values in v_SPECIAL_VARIABLE');
close curv1 ;
end;
游标设计为一次处理一行。如果您想要值的集合,use a collection,而不是游标。
您是否考虑过不使用游标或多语句来实现?
declare
v_offset number:=2;
v_run number:=1;
begin
-- one update
update table2 set column2= CASE WHEN
rowcol between (v_run-1)*v_offset+1 and v_offset*v_run
THEN 'N' ELSE 'n' END
;
end;
如果性能是一个问题,您还需要添加一个 where
子句,以便每次只更新必要的 4 行,而不是 table.[=13= 中的所有行]
迭代游标并逐行更新是导致性能不佳的原因。尽可能摆脱游标,如:
declare
v_offset number:=2;
v_run number:=1;
begin
-- First update
UPDATE TABLE2
SET COLUMN2 = 'N'
WHERE COLUMN1 IN (SELECT DISTINCT COLUMN1
FROM TABLE1
WHERE ROWCOL BETWEEN (v_run-1)*v_offset+1
AND v_offset*v_run);
-- Second update
UPDATE TABLE2
SET COLUMN2 = 'n'
WHERE COLUMN1 NOT IN (SELECT DISTINCT COLUMN1
FROM TABLE1
WHERE ROWCOL BETWEEN (v_run-1)*v_offset+1
AND v_offset*v_run);
end;
请注意,在这种情况下,更新可以简化为:
declare
v_offset number:=2;
v_run number:=1;
begin
-- Second update
UPDATE TABLE2
SET COLUMN2 = 'n'
WHERE COLUMN1 IS NOT NULL;
UPDATE TABLE2
SET COLUMN2 = 'N'
WHERE COLUMN1 IN (SELECT DISTINCT COLUMN1
FROM TABLE1
WHERE ROWCOL BETWEEN (v_run-1)*v_offset+1
AND v_offset*v_run);
end;
祝你好运。
我们如何编写一个 PL SQL 块来一次更新多行。场景是,有两个表 TABLE1,TABLE2
都有一个公共列 COLUMN1
。在匿名块中,游标定义在 TABLE1
.
在 运行 第一次使用块时,即使用 v_run:=1
和 v_offset:=2
时,前两行将在光标中。在 运行 第二次访问该块 v_run:=2
时,TABLE1
的下两行将在游标中,依此类推。
示例代码中的 v_SPECIAL_VARIABLE
应该是
在第一个 运行 上,即 v_run:=1
,前两行(第 1,2 行)被提取到游标中,它们在 TABLE2
中对应的 COLUMN2
值被更新为 'N'
和 TABLE2
中的其余行更新为 'n'
.
在第二个 运行 即 v_run:=2
接下来的两行(第 3,4 行)从游标中的 TABLE1
及其对应的 COLUMN2
值中获取TABLE2
中的行更新为 'N'
,TABLE2
中的其余行更新为 'n'
.
在第三个 运行 即 v_run:=3
接下来的两行(第 5,6 行)从游标中的 TABLE1
及其对应的 COLUMN2
值中获取TABLE2
中的行更新为 'N'
,TABLE2
中的其余行更新为 'n'
.
表 1 包含
id | COLUMN1 | total
-------------------------
1 | 1256480 | 5
2 | 1256481 | 3
3 | 1256482 | 2
4 | 1256483 | 1
5 | 1256484 | 3
6 | 1256485 | 2
7 | 1256486 | 1
8 | 1256487 | 3
表 2 包含
| COLUMN1 | column2
-------------------------
| 1256480 | N
| 1256481 | N
| 1256482 | N
| 1256483 | N
| 1256484 | N
| 1256485 | n
| 1256486 | n
| 1256487 | n
示例代码
declare
v_offset number:=2;
v_run number:=1;
cursor curv1 is
select column1 from
(select rownum rowcol,column1 from table1)
where rowcol between (v_run-1)*v_offset+1 and v_offset*v_run;
begin
open curv1 ;
fetch curv1 into v_SPECIAL_VARIABLE
----- first update
update table2 set column2='N' where
column1=(' ALL the values in v_SPECIAL_VARIABLE');
----- second update
update table2 set column2='n' where
column1 not in (' ALL the values in v_SPECIAL_VARIABLE');
close curv1 ;
end;
游标设计为一次处理一行。如果您想要值的集合,use a collection,而不是游标。
您是否考虑过不使用游标或多语句来实现?
declare
v_offset number:=2;
v_run number:=1;
begin
-- one update
update table2 set column2= CASE WHEN
rowcol between (v_run-1)*v_offset+1 and v_offset*v_run
THEN 'N' ELSE 'n' END
;
end;
如果性能是一个问题,您还需要添加一个 where
子句,以便每次只更新必要的 4 行,而不是 table.[=13= 中的所有行]
迭代游标并逐行更新是导致性能不佳的原因。尽可能摆脱游标,如:
declare
v_offset number:=2;
v_run number:=1;
begin
-- First update
UPDATE TABLE2
SET COLUMN2 = 'N'
WHERE COLUMN1 IN (SELECT DISTINCT COLUMN1
FROM TABLE1
WHERE ROWCOL BETWEEN (v_run-1)*v_offset+1
AND v_offset*v_run);
-- Second update
UPDATE TABLE2
SET COLUMN2 = 'n'
WHERE COLUMN1 NOT IN (SELECT DISTINCT COLUMN1
FROM TABLE1
WHERE ROWCOL BETWEEN (v_run-1)*v_offset+1
AND v_offset*v_run);
end;
请注意,在这种情况下,更新可以简化为:
declare
v_offset number:=2;
v_run number:=1;
begin
-- Second update
UPDATE TABLE2
SET COLUMN2 = 'n'
WHERE COLUMN1 IS NOT NULL;
UPDATE TABLE2
SET COLUMN2 = 'N'
WHERE COLUMN1 IN (SELECT DISTINCT COLUMN1
FROM TABLE1
WHERE ROWCOL BETWEEN (v_run-1)*v_offset+1
AND v_offset*v_run);
end;
祝你好运。