我有两个表,COURSE
和OFFERING
。他们的专栏是:
COURSE (
courseId,
title,
cost,
duration
)
和
OFFERING (
offeringID,
instructor,
startDate,
endDate,
courseId,
locationId
).
我想配置一个触发器,确保在12月(COURSE
列的startDate
列中无法提供持续时间为5天的课程(来自OFFERING
表的持续时间列)表)。我提出了以下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;
触发器已创建,但有错误。
答案 0 :(得分: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 :(得分: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
的参数传递给存储过程并在其中执行各种检查。