如何删除包含过去日期的行并将此行添加到另一个表?

时间:2015-12-25 18:04:26

标签: sql oracle plsql triggers

请帮忙。我有2张桌子。第一个叫做Reservation,第二个叫做LastOrders。

日期类型中有DATE_FROM列,日期类型为DATE:)_ TO。我希望如果表DATE_TO = SYSDATE中的表中的日期然后删除此行并将新行插入表LastOrders我认为触发器可以做到这一点,但我不知道如何。任何的想法?非常感谢你,祝圣诞快乐:)

TABLE RESERVATION
Name                       Null     Type          
-------------------------- -------- ------------- 
ID                         NOT NULL VARCHAR2(25)  
DESCRIPTION                NOT NULL VARCHAR2(100)      
DATE_FROM                  NOT NULL DATE          
DATE_TO                    NOT NULL DATE  

TABLE LASTORDERS
Name                       Null     Type          
-------------------------- -------- ------------- 
ID                         NOT NULL VARCHAR2(25)  
DESCRIPTION                NOT NULL VARCHAR2(100)      
DATE_FROM                  NOT NULL DATE          
DATE_TO                    NOT NULL DATE 

3 个答案:

答案 0 :(得分:1)

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE RESERVATION (
  ID           VARCHAR2(25)  CONSTRAINT RESERVATION__ID__NN NOT NULL,
  DESCRIPTION  VARCHAR2(100) CONSTRAINT RESERVATION__DE__NN NOT NULL,
  DATE_FROM    DATE          CONSTRAINT RESERVATION__DF__NN NOT NULL,
  DATE_TO      DATE          CONSTRAINT RESERVATION__DT__NN NOT NULL
)
/

CREATE TABLE LASTORDERS (
  ID           VARCHAR2(25)  CONSTRAINT LASTORDERS__ID__NN NOT NULL,
  DESCRIPTION  VARCHAR2(100) CONSTRAINT LASTORDERS__DE__NN NOT NULL,
  DATE_FROM    DATE          CONSTRAINT LASTORDERS__DF__NN NOT NULL,
  DATE_TO      DATE          CONSTRAINT LASTORDERS__DT__NN NOT NULL
)
/

CREATE PROCEDURE fulfilReservation(
  I_ID      IN  RESERVATION.ID%TYPE,
  O_SUCCESS OUT NUMBER
)
AS
  r_reservation RESERVATION%ROWTYPE;
BEGIN
  DELETE FROM RESERVATION
  WHERE ID = I_ID
  AND   SYSDATE BETWEEN DATE_FROM AND DATE_TO
  RETURNING ID, DESCRIPTION, DATE_FROM, DATE_TO INTO r_reservation;

  INSERT INTO lastorders VALUES r_reservation;

  o_success := 1;
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    o_success := 0;
END;
/

INSERT INTO RESERVATION VALUES ( 1, 'Test', SYSDATE - 1, SYSDATE + 1 )
/

DECLARE
  success NUMBER(1,0);
BEGIN
  fulfilReservation( 1, success );
END;
/

查询1

SELECT * FROM RESERVATION

<强> Results

No Results

查询2

SELECT * FROM LASTORDERS

<强> Results

| ID | DESCRIPTION |                  DATE_FROM |                    DATE_TO |
|----|-------------|----------------------------|----------------------------|
|  1 |        Test | December, 24 2015 18:59:07 | December, 26 2015 18:59:07 |

答案 1 :(得分:1)

触发器可以完成这样的工作,但它只会在表数据的某些更改时触发。如果您需要实时在表之间移动数据,则必须使用作业。


    begin
      dbms_scheduler.create_job(
         job_name => 'my_job',
         job_type => 'PLSQL_BLOCK',
         enabled => true,
         repeat_interval => 'FREQ=DAILY; INTERVAL=1',
         start_date => round(sysdate,'DD'),
         job_action => 'begin
           insert into LastOrders
           select * 
             from Reservation 
            where DATE_TO = round(sysdate,''DD'');

           delete Reservation where DATE_TO = round(sysdate,''DD'');       
           commit;
         end;');     
    end;

此作业每天00:00将数据从Reservation移至LastOrders。

答案 2 :(得分:0)

噢,狡猾的!

主要问题是&#34;实时&#34;你需要这个。你需要考虑方程两边的数据变化 - 意味着,有新的数据进入表格,应该与SYSDATE(简单的部分)进行比较。另一边是SYSDATE,每秒都在变化。因此,如果您需要尽可能准确的数据,您基本上需要每秒检查整个表格,看看是否有任何DATE_DO已经到达&#34;到SYSDATE。这就是@Artem建议的工作派上用场。

BUT

每天运行一次作业意味着行每天只会移动一次,每秒运行一次就意味着每秒查询一次表(潜在的性能开销)。

所以,你需要聪明一点 -

  1. 在DATE_TO
  2. 上添加索引
  3. 确保重复使用绑定变量 查询你在桌子上做什么。即,更改中的查询 工作。
  4. 以聪明的方式建立工作 - 让我们说你每5次运行一次 min(因为你不希望你的潜在重量级查询运行 每一秒),你检查将到达SYSDATE的行 接下来的5分钟。然后,您可以移动到一个临时表 只有这些行,并且每秒都有另一个作业。
  5. 听起来有点复杂,但如果计划扩展这些数据,可以省去很多麻烦。

    祝你好运,如果你有任何问题,请告诉我。