创建两个表运行的触发

问题描述 投票:5回答:2

我有两个表,COURSEOFFERING。他们的栏目有:

COURSE (
   courseId, 
   title, 
   cost, 
   duration
) 

OFFERING (
    offeringID, 
    instructor, 
    startDate, 
    endDate, 
    courseId, 
    locationId
 ). 

我想配置确保了有5天(从COURSE表的持续时间列)期间的课程不能在十二月提供的(从startDateOFFERING列)的触发器。我想出了下面的SQL查询:

CREATE OR REPLACE TRIGGER checkDuration
BEFORE INSERT OR UPDATE ON 
  (course c JOIN offering o
   ON   
   c.courseId = o.courseId)
FOR EACH ROW
BEGIN
  IF ((to_char(:new.startDate, 'fmMONTH') = 'DECEMBER') AND duration = 5) 
  THEN
     raise_application_error(-20001, 'Courses of five days duration cannot be run in December');
  END IF;
END;

触发器被创造,但有错误。

sql database oracle triggers oracle10g
2个回答
3
投票

这完美地工作。

CREATE OR REPLACE TRIGGER checkDuration
  BEFORE INSERT OR UPDATE on offering
  FOR EACH ROW
DECLARE
  isFound NUMBER;
BEGIN
  SELECT 1 INTO isFound FROM DUAL WHERE EXISTS (
    SELECT * FROM Course c
    WHERE c.courseId = :new.courseId AND c.duration = 5);
  IF EXTRACT(MONTH FROM :new.startDate) = 12 
    THEN RAISE_APPLICATION_ERROR(-20001, 'Courses of five days duration cannot be run in December');
  END IF;
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    NULL;
END;

1
投票

有没有办法,除非你创建隐藏了两个表映射所有应用程序代码这个观点工作的可更新视图来一个触发链接到两个表。但这种方法只有当你从头开始开发新的应用程序启动非常有用。

如果你的目标是保持代码只在一个地方,然后使用一个存储过程或包,并从每个触发调用它。

create or replace procedure CheckDuration(
  pStartdate in date, 
  pDuration  in number
)
is
begin

  if( (extract(month from pStartDate) = 12) and (pDuration = 5) ) then

    raise_application_error(-20001, 
      'Courses of five days duration cannot be run in December'
    );

  end if;

end;
/

CREATE OR REPLACE TRIGGER course_BIU
BEFORE INSERT OR UPDATE ON course for each row
begin

  for cCheck in (
    select o.StartDate from offering o where o.courseId = :new.courseId
  ) loop
    CheckDuration(cCheck.StartDate, :new.Duration);
  end loop;

end;
/

CREATE OR REPLACE TRIGGER offering_BIU
BEFORE INSERT OR UPDATE ON offering for each row
begin

  for cCheck in (
    select c.Duration from course c where c.courseId = :new.courseId
  ) loop
    CheckDuration(:new.StartDate, cCheck.Duration);
  end loop;

end;

为更通用的解决方案可以传递course%rowtype的参数和offering%rowtype到存储过程,并执行内部的各种检查。

© www.soinside.com 2019 - 2024. All rights reserved.