【问题标题】:create pl sql trigger创建pl sql触发器
【发布时间】:2018-04-09 01:08:10
【问题描述】:

我正在尝试为before insert 编写触发器以验证案例日期。 案件日期应在当前日期之前的 5 年和之后的 7 年之间。

例如,2018 年的案例日期应为 2013 年至 2025 年。如果日期超出范围,则触发器应停止插入数据。

CREATE OR REPLACE TRIGGER ch
BEFORE INSERT 
on CASE
FOR EACH ROW 
DECLARE

    CASN number;
BEGIN
    SELECT COUNT(*) 
    INTO CASN
    FROM CASE
    WHERE :new.STARTDATE > SYSDATE;
    IF (CASN > 0) THEN
        RAISE_APPLICATION_ERROR(-20000,'Start DATE CANNOT Be GREATER than today's 
date');
END IF; 
END;

这里STARTDATECASE 表的列

此触发器在开始日期大于今天的日期时启动,但我需要它在超出上述范围时运行。

如何在 sysdate 中添加一个指定的时间间隔,使其适用于上述情况?

【问题讨论】:

    标签: oracle plsql


    【解决方案1】:

    您在Trigger 中使用的逻辑完全错误。您无需使用:NEW.STARTDATE 从表中获取计数。这是您正在寻找的东西。

    CREATE OR replace TRIGGER ch
      BEFORE INSERT ON cases
      FOR EACH ROW
    BEGIN
        IF ( :NEW.casedate < SYSDATE - INTERVAL '5' year
             OR :NEW.casedate > SYSDATE + INTERVAL '7' year ) THEN
          RAISE_APPLICATION_ERROR(-20000,
    'CASE DATE should be in range: current date - 5 years and current date + 7 years')
    ;
    END IF;
    END;
    
    /  
    

    编辑:我没有在日期上添加TRUNC,因为我不确定您在考虑日期范围时是否也要考虑时间部分。如果您可以只考虑天数,您可以使用TRUNC(SYSDATE) 代替SYSDATE。根据您的业务需求进行相应修改。

    另一种选择是使用CHECK 约束。尽管 Oracle 不允许您拥有 在检查约束定义中使用SYSDATE,您可以创建另一个默认为SYSDATE 的列(或重用现有列)并对其应用检查约束。

    ALTER TABLE CASES ADD ( CURR_DATE DATE DEFAULT SYSDATE );
    
    ALTER TABLE CASES ADD CONSTRAINT
    RANGE_CHECK CHECK( casedate > CURR_DATE - INTERVAL '5' YEAR
                       AND casedate < CURR_DATE + INTERVAL '7' YEAR) ENABLE;
    

    【讨论】:

    • 表通常有一个元数据列,例如 DATE_CREATED 来跟踪记录的历史。我们可以在检查约束中使用这样的列。此外,截断日期(当然是下限中的sysdate)可能是一个好主意,以防止时间元素出现明显有效的日期。
    • @APC:谢谢。我在答案中添加了注释。
    【解决方案2】:

    日期算术。 Oracle 数据库使您能够以多种方式对日期和时间戳执行算术运算:

    在日期中添加或减去数值,如 SYSDATE + 7; Oracle 数据库将该数字视为天数。

    添加一个日期或从另一个日期减去它,如 l_hiredate - SYSDATE。
    使用内置函数将日期“移动”指定的月数或一周内的另一个日期。

    以下是一些带有日期和数字的日期算术示例(假设在所有情况下 l_date 变量已被声明为 DATE):

    Set a local variable to tomorrow’s date: 
    
    
    
    l_date := SYSDATE + 1;
    
    
    Move back one hour:
    
    
    
    l_date := SYSDATE - 1/24;
    
    
    Move ahead 10 seconds:
    
    
    
    l_date := SYSDATE + 10 / (60 * 60 * 24);
    

    当您将一个日期添加到另一个日期或从另一个日期减去它时,结果是两者之间的天数。结果,执行这个块:

        DECLARE
           l_date1   DATE := SYSDATE;
           l_date2   DATE := SYSDATE + 10;
        BEGIN
           DBMS_OUTPUT.put_line (
              l_date2 - l_date1);
           DBMS_OUTPUT.put_line (
              l_date1 - l_date2);
        END;
    

    返回以下输出:

    10 -10

    【讨论】:

    • 可以从其他网站发布内容,但您也必须给予应有的信任:添加对oracle.com/technetwork/issue-archive/2012/12-jan/…的引用
    • @KaushikNayak - 实际上,我认为通过从另一个网站批发剪切'n'paste 来构建答案是不可接受的,特别是因为它的原作者确实回答了 StackOverflow 上的问题。跨度>
    • 我只是想帮助他............如果您自己编写代码而不是当您从stackoverflow @APC复制粘贴时,代码会更好地理解
    • 剪切并粘贴另一个人的工作(逐字记录和不承认)似乎是鼓励某人编写自己的代码的一种奇怪方式。除此之外,这个答案并没有解决 OP 的实际问题。如果你真的像 KaushikNayak 那样针对这个问题写了一个正确的答案,那就更好了。
    • 阿努杰,我理解你的想法。但是,与互联网上的任何其他技术论坛不同,本网站的答案维护了某些标准。您的回答可能很好,但绝对没有帮助。因此,为避免进一步的投票和 Facebook 风格的 cmets 和争论,我建议您删除此答案。没有怨恨的朋友......祝你有美好的一天......
    猜你喜欢
    • 2018-04-01
    • 2013-06-03
    • 2014-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-18
    • 2011-08-06
    • 2021-12-27
    相关资源
    最近更新 更多