2017-03-15 4 views
0

を失敗しました:トリガー - 無効であると私はこの単純なトリガーを作成しようとしている再検証

Trigger created 

しかし、私は私のテーブル更新:実行時に

CREATE OR REPLACE TRIGGER my_trig 
    BEFORE DELETE OR INSERT OR UPDATE ON empcopy 
    FOR EACH ROW 
    WHEN (NEW.EID > 0) 
    DECLARE 
    sal_diff number; 
    BEGIN 

sal_diff := :NEW.salary - :OLD.salary; 
dbms_output.put_line('Old salary: ' || :OLD.salary); 
dbms_output.put_line('New salary: ' || :NEW.salary); 
dbms_output.put_line('Salary difference: ' || sal_diff); 
COMMIT; 
    END; 
/

をそのような結果を与えます次のような結果が得られた:

update empcopy 
    set salary=salary+5000; 

実行後:

error at line 1 
    ORA-0498:triiger 'HR.MY_TRIG' is invalid and failed re-validation. 
+0

はルックス: //stackoverflow.com/questions/22668507/oracle-trigger-ora-04098-trigger-is-invalid-and-failed-re-validation – Debangshu

+0

このソリューションでは動作しません。 –

+0

@Jaskunwarsinghこの回答は完全な実例で更新されました。提供されている例を実行し、エラーが発生した場合はお知らせください。また、あなたのオラクルのバージョンを含むことはしばしば役に立ちます。 – alexgibbs

答えて

0

DECLAREブロックにPRAGMA AUTONOMOUS_TRANSACTIONを使用せずにCOMMITを使用することはできません。個々の文のすべての行は、その変更を完了しなければなりません - データベースが行レベルのトリガーにコミット許可された場合は他の人が評価されていたとのユニットとして文を乱す前に
することは、これは、ステートメント内の行の一部をコミット可能にすることができます一緒に約束してください。
このトリガーでAUTONOMOUS_TRANSACTIONを使用する場合は、オープン・トランザクション内の他のアクティブなDML変更とは独立したトランザクションで、トリガーが新規UPDATE秒、DELETE秒などを実行できるようになります。
ただし、TRIGGERDMLを実際に実行しておらず、読み込みも行っていないため、COMMITはまったく必要ありません。あなたがする必要があるのは、以下のようにCOMMITをドロップすることだけです。

CREATE OR REPLACE TRIGGER my_trig 
BEFORE DELETE OR INSERT OR UPDATE ON empcopy 
FOR EACH ROW 
WHEN (NEW.EID > 0) 
    DECLARE 
    sal_diff number; 
    BEGIN 

    sal_diff := :NEW.salary - :OLD.salary; 
    dbms_output.put_line('Old salary: ' || :OLD.salary); 
    dbms_output.put_line('New salary: ' || :NEW.salary); 
    dbms_output.put_line('Salary difference: ' || sal_diff); 
    END; 
/

ただし、他にもいくつかの変更点があります。他のトリガーとして
NEW値を変更することができ、あなただけの最終状態を記録するために、このAFTER TRIGGERすることを検討することがあります。 DELETE sがすべてNULL:NEW.EIDを持つことになりますので、
また、このトリガは、任意のDELETE秒を記録しません。ログDELETEが意図されていない場合はAFTER DELETEを削除するか、CASE WHEN DELETINGステートメントを使用してDELETEを別々に処理することをお勧めします。

CREATE OR REPLACE TRIGGER MY_TRIG 
AFTER DELETE OR INSERT OR UPDATE ON EMPCOPY 
FOR EACH ROW 
    DECLARE 
    SAL_DIFF NUMBER; 
    BEGIN 
    CASE WHEN DELETING 
     THEN 
     DBMS_OUTPUT.put_line('Log the delete here if you want.'); 
     WHEN (:NEW.EID > 0) 
     THEN 
     SAL_DIFF := COALESCE(:NEW.SALARY, 0) - COALESCE(:OLD.SALARY, 0); 
     DBMS_OUTPUT.put_line('Old salary: ' || :OLD.SALARY); 
     DBMS_OUTPUT.put_line('New salary: ' || :NEW.SALARY); 
     DBMS_OUTPUT.put_line('Salary difference: ' || SAL_DIFF); 
    ELSE NULL; 
    END CASE; 
    END; 
/

また、DBMS_OUTPUTは一時的なログです。 EMPCOPYの変更の記録をより永続的に保持したい場合は、監査証跡やFGAなど、データの変更追跡を自動化して制御するためのツールが用意されています。

EDIT:下記の例。

テストテーブルを作成します。

CREATE TABLE EMPCOPY(
    EID NUMBER NOT NULL, 
    SALARY NUMBER 
); 
Table EMPCOPY created. 

その後、トリガーを作成します。

CREATE OR REPLACE TRIGGER MY_TRIG 
AFTER DELETE OR INSERT OR UPDATE ON EMPCOPY 
FOR EACH ROW 
    DECLARE 
    SAL_DIFF NUMBER; 
    BEGIN 
    CASE WHEN DELETING 
     THEN 
     DBMS_OUTPUT.put_line('Log the delete here if you want.'); 
     WHEN (:NEW.EID > 0) 
     THEN 
     SAL_DIFF := COALESCE(:NEW.SALARY, 0) - COALESCE(:OLD.SALARY, 0); 
     DBMS_OUTPUT.put_line('Old salary: ' || :OLD.SALARY); 
     DBMS_OUTPUT.put_line('New salary: ' || :NEW.SALARY); 
     DBMS_OUTPUT.put_line('Salary difference: ' || SAL_DIFF); 
    ELSE NULL; 
    END CASE; 
    END; 
/
Trigger MY_TRIG compiled 

そして、それをテストします。http:非常によく似た質問があったよう

SQL> --Should not log, EMPID is not greater than zero. 
SQL> INSERT INTO EMPCOPY VALUES (-13, 50000); 
1 row inserted. 
SQL> --Should log, EMPID is greater than zero. 
SQL> INSERT INTO EMPCOPY VALUES (1919, 75000); 
Old salary: 
New salary: 75000 
Salary difference: 75000 
1 row inserted. 
SQL> -- The statement you provided. This should log for EMPID=1919 but not EMPID=-13 
SQL> update empcopy 
    2 set salary=salary+5000; 
Old salary: 75000 
New salary: 80000 
Salary difference: 5000 
2 rows updated. 
SQL> -- This should log a PLACEHOLDER value for each row on delete. 
SQL> DELETE FROM EMPCOPY; 
Log the delete here if you want. 
Log the delete here if you want. 
2 rows deleted. 
+0

しかし、empcopyを更新すると、エラーが発生します。 –

+0

@Jaskunwarsinghエラーは何ですか?どのバージョンのトリガーを使用していますか、前か後ですか?トリガーを作成するために使用したコードとエラーをスローするコードを投稿してください。物事を評価するために何が実行されているのかを確認するのに役立ちます。また、使用しているOracleのバージョンは?ありがとう – alexgibbs

関連する問題