2

私はSQLを初めて使用し、監査テーブルに挿入するトリガーを作成しようとしています。

create or replace trigger late_ship_insert
  after insert on suborder
  for each row
declare
  employee int;
begin
  select emp_id 
    into employee
    from handles
   where order_no = :new.order_no;
  if :new.actual_ship_date > :new.req_ship_date then
    insert into ship_audit
      values (employee, :new.order_no, :new.suborder_no, :new.req_ship_date, :new.actual_ship_date);
end;

エラー:

Warning: execution completed with warning
trigger late_ship_insert Compiled.

しかし、挿入ステートメントを試してみると、トリガーがそれを削除するように機能していないことがわかります。

Error starting at line 1 in command:
insert into suborder 
    values  ( 8, 3, '10-jun-2012', '12-jul-2012', 'CVS', 3) 
Error at Command Line:1 Column:12
Error report:
SQL Error: ORA-04098: trigger 'COMPANY.LATE_SHIP_INSERT' is invalid and failed re-validation
04098. 00000 -  "trigger '%s.%s' is invalid and failed re-validation"
*Cause:    A trigger was attempted to be retrieved for execution and was
           found to be invalid.  This also means that compilation/authorization
           failed for the trigger.
*Action:   Options are to resolve the compilation/authorization errors,
           disable the trigger, or drop the trigger.

何がこれを引き起こしているのか、どんな助けでも大歓迎です。ありがとう!

4

1 に答える 1

3

コードをフォーマットするときに明らかになるエラーは、IFステートメントにEND IF

create or replace trigger late_ship_insert
  after insert on suborder
  for each row
declare
  employee int;
begin
  select emp_id 
    into employee
    from handles
   where order_no = :new.order_no;
  if :new.actual_ship_date > :new.req_ship_date then
    insert into ship_audit
      values (employee, :new.order_no, :new.suborder_no, :new.req_ship_date, :new.actual_ship_date);
  end if;
end;

一般的な問題として、ステートメントがすべての列の値を指定し、それらを適切な順序で指定するINSERTという事実に依存するのではなく、ステートメント内の宛先テーブルの列を常にリストする必要があります。INSERTたとえば、誰かがテーブルに列を追加しても無効にならないため、コードははるかに堅牢になります。これは次のようになります(ship_auditテーブルの列の名前を推測しています)

create or replace trigger late_ship_insert
  after insert on suborder
  for each row
declare
  employee int;
begin
  select emp_id 
    into employee
    from handles
   where order_no = :new.order_no;
  if :new.actual_ship_date > :new.req_ship_date then
    insert into ship_audit( emp_id, order_no, suborder_no, req_ship_date, actual_ship_date )
      values (employee, :new.order_no, :new.suborder_no, :new.req_ship_date, :new.actual_ship_date);
  end if;
end;
于 2012-07-19T20:58:11.600 に答える