根据大小删除 Oracle 行

Delete Oracle rows based on size

我有这个 Oracle table,我想在达到 2000 行数据时不时清理它:

CREATE TABLE AGENT_HISTORY(
  EVENT_ID INTEGER NOT NULL,
  AGENT_ID INTEGER NOT NULL,
  EVENT_DATE DATE NOT NULL
)
/

当 table 达到 2000 行时,如何从 table 中删除最旧的行?

创建一个 DBMS_JOB 或 DBMS_SCHEDULER,在一定时间间隔后开始并调用一个过程。在该过程中,检查计数并删除基于 event_date.

的行

抱歉,我到现在才看到您的评论。这是您正在寻找的代码。确保您有创建调度程序和作业的资金。此代码假定 event_id 是#s 序列并与 event_date 保持一致。否则根据时间和 ID 或您的选择更改排名。您也可以更改时间间隔。检查 DBMS_SCHEDULER 包文档是否有任何错误和更正。

create or replace procedure proc_house_keeping is
begin
  delete
    from (
    select rank() over (order by event_id desc) rnk
      from agent_history 
   )
    where rnk > 2000;
  commit;
end;
/

begin
  dbms_scheduler.create_program(
  program_name   => 'PROG_HOUSE_KEEPING',
  program_type   => 'STORED_PROCEDURE',
  program_action => 'PROC_HOUSE_KEEPING',
  number_of_arguments => 0,
  enabled        => FALSE,
  comments       => 'Procedure to delete rows greater than 2000');
end;
/

begin
  dbms_scheduler.create_job(
      job_name => 'table_house_keeping',
      program_name => 'PROG_HOUSE_KEEPING',
      start_date => dbms_scheduler.stime,
      repeat_interval => 'FREQ=MINUTELY;INTERVAL=1',
      end_date => dbms_scheduler.stime+1,
      enabled => false,
      auto_drop => false,
      comments => 'table house keeping, runs every minute');
end;
/

您可以使用以下查询删除除最新的 2000 行以外的所有行:

DELETE FROM agent_history a
 WHERE 2000 < ( SELECT COUNT(1) cnt FROM agent_history b WHERE b.event_date < a.event_date )

查询检查 table (a) 中的每一行,以查看有多少行 event_date 小于该行。如果比它少2000多行,那么它会删除那一行。

如果这不起作用,请告诉我。

一种方法可能是向您的 table 添加触发器,以便它在每个 INSERT 语句中检查并删除最旧的行;例如,假设不超过 3 行:

CREATE OR REPLACE TRIGGER DELETE_3
AFTER INSERT ON AGENT_HISTORY
DECLARE
    vNum    number;
    minDate date;
BEGIN

    delete AGENT_HISTORY
    where (event_id, agent_id, event_date) in
             (  select event_id, agent_id, event_date
                from (        
                        select event_id, agent_id, event_date, row_number() over (order by event_date desc) num
                        from AGENT_HISTORY
                     )
                where num > 3 /* MAX NUMBER OF ROWS = 3*/
             );
END;

假设我们插入 5 行:

SQL> begin
  2      insert into AGENT_HISTORY(EVENT_ID , AGENT_ID, EVENT_DATE) values ( 1, 1, sysdate);
  3      dbms_lock.sleep(1);
  4      insert into AGENT_HISTORY(EVENT_ID , AGENT_ID, EVENT_DATE) values ( 2, 2, sysdate);
  5      dbms_lock.sleep(1);
  6      insert into AGENT_HISTORY(EVENT_ID , AGENT_ID, EVENT_DATE) values ( 3, 3, sysdate);
  7      dbms_lock.sleep(1);
  8      insert into AGENT_HISTORY(EVENT_ID , AGENT_ID, EVENT_DATE) values ( 4, 4, sysdate);
  9      dbms_lock.sleep(1);
 10      insert into AGENT_HISTORY(EVENT_ID , AGENT_ID, EVENT_DATE) values ( 5, 5, sysdate);
 11      commit;
 12  end;
 13  /

PL/SQL procedure successfully completed.

我们只有最新的 3 个:

SQL> select * from  AGENT_HISTORY;

  EVENT_ID   AGENT_ID EVENT_DATE
---------- ---------- ---------------------------------------------------------------------------
         3          3 18-FEB-16 17:05:24,000000
         4          4 18-FEB-16 17:05:25,000000
         5          5 18-FEB-16 17:05:26,000000