0

社長でもマネージャーでもない従業員に 10,000 ドルを超える給与を与えることを禁止するトリガー「restrict_salary」を作成しようとしています。「更新」が列「sal」に影響しない場合、トリガーはトリガーされません。その後、9%以上の増加も禁止するきっかけにしようと考えていた。私は何かを試しましたが、行き詰まっています。これが私のコードです。

CREATE OR REPLACE TRIGGER restrict_salary
BEFORE
UPDATE OF sal
ON EMP
REFERENCING emp AS new_emp
FOR EACH ROW
WHEN (sal > 10000)
BEGIN
DECLARE job VARCHAR2(30);
    select job into job from ename;
    IF job!='MANAGER' OR job != 'PRESIDENT' THEN
        raise_application_error (-20002, 'Cannot attribute more than 10000 dollars ');
    END IF;

END;
/
4

1 に答える 1

3

あなたは間違った方法を持っbeginています。declarePL/SQL ブロックを開始する前に、変数を宣言する必要があります。

また、必要に応じて WHEN 句を変更および追加しbefore update of sal on empましたbefore update on empnew.

CREATE OR REPLACE TRIGGER restrict_salary
BEFORE UPDATE ON EMP
FOR EACH ROW
WHEN (new.sal > 10000)
DECLARE 
   job ename.job%type;
BEGIN
    -- THERE WAS A MISSING WHERE CLAUSE!!!
   select job into job from ename where empid = :new.id;

   IF job not in ('MANAGER', 'PRESIDENT') THEN
      raise_application_error (-20002, 'Error that fit''s on page');
   END IF;

END restrict_salary;
/

最大の問題は、 の WHERE 句が欠落していることselect into ...です。これは、このテーブルに複数の行がある場合、常に TOO_MANY_ROWS エラーが発生することを意味します。ご覧のとおり、これを変更しましたが、スキーマによっては再度変更する必要がある場合があります。

明確にするために、ステートメントにトリガーの名前を追加しend、不要なreferencing句を削除しました。これらはどちらも機能させるためには不要ですが、読みやすさには役立ちます。

最後に、変数jobを取得元の列の型として宣言しました。これにより、テーブル内の列を変更しても、トリガーにはまったく影響を与えません。このようなテーブルに依存する変数を常に宣言することは賢明です。これにより、データベースの変更によって引き起こされるエラーの数が大幅に減少し、コード ベースの難読化が大幅に減少します。

ドキュメントを読んで構文を理解することを強くお勧めします。

于 2012-11-11T22:31:38.190 に答える