首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >创建在两个表上运行的触发器

创建在两个表上运行的触发器
EN

Stack Overflow用户
提问于 2013-08-08 23:46:01
回答 2查看 41.7K关注 0票数 5

我有两张桌子,COURSEOFFERING。它们的列是:

代码语言:javascript
复制
COURSE (
   courseId, 
   title, 
   cost, 
   duration
) 

代码语言:javascript
复制
OFFERING (
    offeringID, 
    instructor, 
    startDate, 
    endDate, 
    courseId, 
    locationId
 ). 

我想配置一个触发器,以确保持续时间为5天(来自COURSE表的duration列)的课程不能在12月份提供(来自OFFERING表的startDate列)。我提出了以下SQL查询:

代码语言:javascript
复制
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;

触发器已创建,但有错误。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-08-09 21:25:32

这样做效果很好。

代码语言:javascript
复制
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;
票数 3
EN

Stack Overflow用户

发布于 2013-08-09 00:51:06

没有办法将一个触发器链接到两个表,除非您创建一个可更新的视图来隐藏这两个表,并映射所有应用程序代码以使用此视图。但是这个解决方案只有在你开始从头开始开发新的应用程序时才有用。

如果您的目标是只将代码放在一个位置,则使用存储过程或包,并从每个触发器调用它。

代码语言:javascript
复制
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%rowtypeoffering%rowtype的参数传递给存储过程,并在其中执行各种检查。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18130424

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档