我想使用 Oracle 存储过程从表中批量删除 90 天的记录。
首先,我想从
tbl1
中获取一年的记录,然后从该游标中获取 90 天的记录,然后继续从 tbl1
和 tbl2
中批量删除 90 天范围,并分别提交每个批次,所以我将有一年范围记录的最大 0f 4 提交。
但是以下存储过程是逐行删除而不是批量删除。我想知道如何使用 Oracle 存储过程达到预期结果?谢谢
CREATE OR REPLACE PROCEDURE pr2
AS
TYPE bulk_type IS TABLE OF tbl1.nameid%type;
v_batch bulk_type;
v_size number;
v_time TIMESTAMP := CURRENT_TIMESTAMP;
v_max_time INTERVAL DAY TO SECOND := INTERVAL '0 00:05:00' DAY TO SECOND;
CURSOR deleter IS
SELECT nameid
FROM tbl1
WHERE regDate >= '01-Jan-22' AND regDate <= '01-Dec-22'
ORDER BY regDate;
BEGIN
OPEN deleter;
FETCH deleter BULK COLLECT INTO v_batch;
WHILE deleter%FOUND LOOP
for delete_buk in (select nameid from tbl1 where regDate <= (select min(regDate) + interval '90' day from tbl1)
and nameid in (v_batch.nameid));
LOOP
BEGIN
DELETE FROM tbl2
WHERE nameid = delete_buk.nameid;
DELETE FROM tbl2
WHERE id = delete_buk.nameid;
v_size:= sql%rowcount;
COMMIT;
INSERT INTO log(log_t) VALUES (v_size || ' id deleted');
IF CURRENT_TIMESTAMP - start_time >= max_time THEN
EXIT;
END IF;
END LOOP;
CLOSE deleter;
END pr2;
不要使用循环,只需一次性删除行:
CREATE PROCEDURE pr2
AS
BEGIN
DELETE FROM tbl2
WHERE EXISTS(
SELECT 1
FROM tbl1
WHERE regDate >= DATE '2022-01-01'
AND regDate < DATE '2023-01-01'
AND ( tbl1.nameid = tbl2.nameid
OR tbl1.id = tbl2.id )
);
v_size:= sql%rowcount;
INSERT INTO log(log_t) VALUES (v_size || ' id deleted');
END pr2;
/
如果您确实想分 4 组删除它,请以 3 个月为单位删除它(因为一年有 365 或 366 天,而不是 4-lots-of-90,即 360 天):
CREATE PROCEDURE delete_tbl2_range(
i_start_date IN DATE,
i_end_date IN DATE
)
AS
BEGIN
DELETE FROM tbl2
WHERE EXISTS(
SELECT 1
FROM tbl1
WHERE regDate >= i_start_date
AND regDate < i_end_date
AND ( tbl1.nameid = tbl2.nameid
OR tbl1.id = tbl2.id )
);
v_size:= sql%rowcount;
INSERT INTO log(log_t) VALUES (v_size || ' id deleted');
END delete_tbl2_range;
/
CREATE PROCEDURE pr2
AS
BEGIN
DELETE_TBL2_RANGE(DATE '2022-01-01', DATE '2022-04-01');
DELETE_TBL2_RANGE(DATE '2022-04-01', DATE '2022-07-01');
DELETE_TBL2_RANGE(DATE '2022-07-01', DATE '2022-10-01');
DELETE_TBL2_RANGE(DATE '2022-10-01', DATE '2023-04-01');
END pr2;
/
注意:您不应该在过程中使用
COMMIT
,因为它会阻止您将多个过程链接在一起,并且如果后一个过程失败,请使用 ROLLBACK
将它们全部回滚。相反,COMMIT
来自您调用过程的代码。