5

私は2つのテーブルを持っていCOURSEますOFFERING. それらの列は次のとおりです。

COURSE (
   courseId, 
   title, 
   cost, 
   duration
) 

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

期間が 5 日間のコース (表の期間列から) が 12 月 (表の列COURSEから) に提供されないようにするトリガーを構成したいと考えています。次のSQLクエリを思いつきました:startDateOFFERING

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;

トリガーは作成されましたが、エラーがあります。

4

2 に答える 2

1

1 つのトリガーを 2 つのテーブルにリンクする方法はありません。更新可能なビューを作成して両方のテーブルを非表示にし、このビューで動作するようにすべてのアプリケーション コードをマップする場合を除きます。ただし、このソリューションは、新しいアプリケーションをゼロから開発する場合にのみ役立ちます。

コードを 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

于 2013-08-08T16:51:06.117 に答える