根据大小删除Oracle行

时间:2016-02-18 14:58:37

标签: sql oracle oracle11g oracle10g

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

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

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

3 个答案:

答案 0 :(得分:3)

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

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

查询检查表(a)中的每一行,以查看event_date少于该行的行数。如果有超过2000行,那么它将删除该行。

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

答案 1 :(得分:1)

创建一个DBMS_JOB或DBMS_SCHEDULER,它会在一定时间间隔后启动并调用一个过程。在该过程中,检查计数并根据event_date删除行。

抱歉,直到现在我才看到你的评论。这是您要寻找的代码。确保您有资金来创建调度程序和作业。此代码假定event_id是一系列#s并与event_date保持一致。否则,根据时间和身份或您选择的方式更改排名。您也可以更改时间间隔。检查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;
/

答案 2 :(得分:0)

一种方法可能是在表中添加一个触发器,以便它检查并删除每个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