如何使用Oracle SQL存储过程批量删除

问题描述 投票:0回答:1

我想使用 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;
sql stored-procedures plsql oracle-sqldeveloper rowdeleting
1个回答
0
投票

不要使用循环,只需一次性删除行:

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
来自您调用过程的代码。

© www.soinside.com 2019 - 2024. All rights reserved.