Oracle 触发器检查一个表中的课程持续时间,如果课程是特定日期,则阻止更新

Posted

技术标签:

【中文标题】Oracle 触发器检查一个表中的课程持续时间,如果课程是特定日期,则阻止更新【英文标题】:Oracle trigger to check course duration in one table and prevent update if course is a particular date 【发布时间】:2013-03-26 17:09:22 【问题描述】:

如果我提出的问题已经在其他地方得到解答,但我很难找到合适的答案,请提前致歉。我知道如何基于一个表创建简单的触发器,但是我试图实现跨两个表的链接更新。场景如下: course 表中有一个 duration 列,而 products 表中有一个 start_date 列。课程是提供课程并且两个表(课程和课程)通过 course_id 链接的实例。如果对应的课程持续时间为 5 天,我需要创建一个触发器,以防止产品表在 1 月期间具有开始日期。我已尝试创建此触发器并可以发布我的努力,但我敢肯定,我绝对远离。

CREATE OR REPLACE TRIGGER check_duration
  BEFORE UPDATE on offering
  FOR EACH ROW
BEGIN
  SELECT c.duration
  INTO duration
  FROM course c
  WHERE c.duration = 5
IF(:new.start_date BETWEEN to_date('01/01/2013', 'DD/MM/YYY') AND to_date('31/01/2013', 'DD/MM/YYY')
  THEN RAISE_APPLICATION_ERROR(20100, 'Cannot run particular course during this month')
END IF;
END;

课程表:

Course_id(pk) | Title | Duration | Cost

报价表:

offering_id(pk) | start_date | location | instructor | course_id(fk)

还有另外两个表出勤率和学生我认为我不需要为这个问题发布这些表的构造

【问题讨论】:

你能贴出你试过的代码吗? 发布您的代码。触发器可以轻松运行查询,然后取决于您实际想要对结果执行的操作。 如果之后将持续时间更改为 5 天会发生什么情况(并且提供的记录中存在违反规则的记录?) 嗨蒂姆,持续时间是固定的 我会将持续时间放在产品表中。 【参考方案1】:

如果有关于表格的任何新信息,您可能需要对此进行调整,但这里是基于您的评论的初步刺伤,即offering 表格中有一个 courseid 列:

CREATE OR REPLACE TRIGGER check_duration
  BEFORE UPDATE on offering
  FOR EACH ROW
DECLARE
  isFound NUMBER;
BEGIN
  -- Just want to know if there's a duration 5 record for the course...
  SELECT 1 INTO isFound FROM DUAL WHERE EXISTS (
    SELECT * FROM course c
    WHERE c.course_id = :NEW.course_id AND c.duration = 5);
  -- Fallthrough to here means a course was found with duration 5. Is
  -- it scheduled for January (month #1) of any year?
  IF EXTRACT(MONTH FROM :NEW.start_date) = 1 THEN
    THEN RAISE_APPLICATION_ERROR(20100, 'Cannot run particular course during this month');
  END IF;
EXCEPTION
  -- If the query didn't find a course with duration 5 it throws
  -- a NO_DATA_FOUND exception. Ignore the exception because not
  -- finding a course means it's OK to add the row.
  WHEN NO_DATA_FOUND THEN
    NULL;
END;

【讨论】:

您可以使用“select count(*)”避免异常 优秀点@knagaev,谢谢!当我只需要一次点击时,我通常会达到“如果存在”,因为如果有大量匹配的行进行计数,它会快得多。但在这种情况下,可能没有,并且计数可能更容易让 OP 理解,这很重要。没有迹象表明 OP 已尝试过此操作,但如果他们这样做并且无法理解异常处理,我将对其进行重新设计以使用 COUNT。 @EdGibbs 感谢您的帮助,我尝试了您的建议,但是我收到以下错误-错误(7,24):PLS-00049:绑定变量错误'NEW.COURSEID'-有什么想法吗? @Matthew - 这意味着您的 courseid 表上没有 courseid 列。我从上面的 cmets 中认为你做到了。你能发布你的courseoffering 表结构吗?这将对我和所有参与该主题的人有所帮助。 @EdGibbs 在提供表中有一个 course_id 列,它是 course_id 的 FK,我现在将发布表结构

以上是关于Oracle 触发器检查一个表中的课程持续时间,如果课程是特定日期,则阻止更新的主要内容,如果未能解决你的问题,请参考以下文章

如何使用oracle中的触发器从另外两个表中插入一个表中的数据

可以为当前会话禁用 Oracle 触发器吗?

Oracle - 在插入前触发检查约束

无法删除或截断 oracle 中的表

如果触发器中的语句不起作用 SQL(Oracle)

用触发器如何在java中删除数据库中两个表中的记录(两个表有关联如表A.aID=表B.bID)