插入新行时自动更新日期

时间:2014-10-26 08:17:10

标签: sql oracle triggers

我正在尝试创建一个触发器,只要添加新行,它就会将列日期更新一个月。

这就是我所拥有的,有人能告诉我我做错了什么吗?

CREATE OR REPLACE TRIGGER tg_nextupdate
BEFORE INSERT
ON Vehicle
FOR EACH ROW
BEGIN
    IF :NEW.NextUpdate = SYSDATE
    THEN
    SET NextUpdate = ADD_MONTHS(SYSDATE,1);
    END IF;
END;

3 个答案:

答案 0 :(得分:1)

不需要IF-END IF块,只要插入新行,它就会有sysdate。因此,只需直接将NextUpdate更新为ADD_MONTHS(SYSDATE,1)即可。不需要检查IF :NEW.NextUpdate = SYSDATE

CREATE OR REPLACE TRIGGER tg_nextupdate
BEFORE INSERT
ON Vehicle
FOR EACH ROW
BEGIN
   :NEW.NextUpdate = ADD_MONTHS(SYSDATE,1);
END;

答案 1 :(得分:0)

当NextUpdate仅包含日期时,您可能会遇到代码问题,而不包括小时,分钟和秒。 试试这个:

CREATE OR REPLACE TRIGGER tg_nextupdate
BEFORE INSERT
ON Vehicle
FOR EACH ROW
BEGIN
    IF :NEW.NextUpdate = trunc(SYSDATE)
    THEN
    SET NextUpdate = ADD_MONTHS(SYSDATE,1);
    END IF;
END;

或者向我们提供有关您想要的内容以及代码内容的更多详细信息。

答案 2 :(得分:0)

  

这就是我所拥有的,有人可以告诉我我做错了什么吗?

假设NextUpdate拥有默认值SYSDATE,正如已经说过的那样,IF可能是"没必要" ...

... 但是,就我而言,我认为真正的问题是SYSDATE并不能保证在每次调用时都返回相同的值。如果您不相信我,请尝试http://sqlfiddle.com/#!4/1f810/2

因此,您的专栏可能会被SYSDATE正确初始化,例如" 2014年10月26日18:50:10 + 0000"。但是,在您的触发器中,SYSDATE可能会很快返回" 2014年10月26日18:50:11 + 0000"。我承认,这将是运气不好。也许这在您的应用程序中是可以接受的。但在更一般的情况下,这可能很容易成为难以追踪的错误。

根据您的需要,我建议改为这三个选项中的一个:

1)假设SYSDATE是一个神奇的值"意思是"嘿触发器!为NextUpdate":

计算正确的值
CREATE OR REPLACE TRIGGER tg_nextupdate
BEFORE INSERT
ON Vehicle
FOR EACH ROW
BEGIN
    IF :NEW.NextUpdate <= SYSDATE
    THEN
        :NEW.NextUpdate := SYSDATE + INTERVAL '1' MONTH;
    END IF;
END;

因此,过去任何时候都会触发新NextUpdate的计算。包括过去的1。

2)从触发器覆盖NextUpdate - 始终:

CREATE TABLE Vehicle (value NUMBER(10),
                NextUpdate DATE)
--              ^^^^^^^^^^^^^^^
--          No need for default here
--          as we override values
/

CREATE OR REPLACE TRIGGER tg_nextupdate
BEFORE INSERT
ON Vehicle
FOR EACH ROW
BEGIN
    :NEW.NextUpdate := SYSDATE + INTERVAL '1' MONTH;
END;
/

INSERT INTO Vehicle(value) VALUES (1)
/
INSERT INTO Vehicle VALUES (2, TO_DATE('30/10/2014','DD/MM/YYYY'))
/
INSERT INTO Vehicle VALUES (3, TO_DATE('30/12/2014','DD/MM/YYYY'))
/
INSERT INTO Vehicle VALUES (4, NULL)
/

3)将NextUpdate默认设置为SYSDATE + INTERVAL&#39; 1&#39; MONTH,允许用户在插入时更改它。 如果您需要,触发器可能会保留LEAST值(+/- 1秒错误,如前言中所述):

CREATE TABLE Vehicle (value NUMBER(10),
                NextUpdate DATE DEFAULT SYSDATE + INTERVAL '1' MONTH)
--              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
--                   set default to the "most probable" value
/

CREATE OR REPLACE TRIGGER tg_nextupdate
BEFORE INSERT
ON Vehicle
FOR EACH ROW
DECLARE
    LimitNextUpdate DATE := SYSDATE + INTERVAL '1' MONTH;
BEGIN
    :NEW.NextUpdate := LEAST(LimitNextUpdate, 
                             NVL(:NEW.NextUpdate,LimitNextUpdate));
    --                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    --                      required if the used set the value to NULL
END;
/

INSERT INTO Vehicle(value) VALUES (1)
/
INSERT INTO Vehicle VALUES (2, TO_DATE('30/10/2014','DD/MM/YYYY'))
/
INSERT INTO Vehicle VALUES (3, TO_DATE('30/12/2014','DD/MM/YYYY'))
/
INSERT INTO Vehicle VALUES (4, NULL)
/

您需要添加额外的逻辑(在触发器中或作为检查约束),以便在过去拒绝NextUpdate