1
customers:
+------------+--------------+ 
| cid        | Name         | 
+------------+--------------+ 
| 1          | Bob          |
| 2          | John         | 
| 3          | Jane         | 
+------------+--------------+ 
accounts:
+------------+--------------+ 
| aid        | type         | 
+------------+--------------+ 
| 1          | Checking     |
| 2          | Saving       | 
| 3          | Checking     | 
+------------+--------------+ 
transactions:
+------------+--------------+--------------+--------------+ 
| tid        | cid          | aid          | type         |
+------------+--------------+--------------+--------------+ 
| 1          | 1            | 1            | Open         |
| 2          | 2            | 3            | Open         |
| 3          | 1            | 2            | Open         |
| 4          | 2            | 3            | Deposit      |
+------------+--------------+--------------+--------------+

新しいアカウントが正常に開かれたときにログテーブルに書き込むトリガーを書き込もうとしています。

今私はこれを持っています:

CREATE OR REPLACE TRIGGER acc_opened
BEFORE INSERT ON transactions
FOR EACH ROW
DECLARE
    c_name customers.name%TYPE;
BEGIN
    IF :new.type = 'Open' THEN
        SELECT name into c_name
        FROM customers c
        WHERE c.cid = :new.cid;

        INSERT INTO logs (who, what) VALUES (c_name, 'An account has been opened');
END;
/    

私が持っているコードは機能せず、ここからどこに行くべきかわかりません。

トリガーは完了しますが、起動すると次のエラーメッセージが表示されます。

PLS-00103:次のいずれかが必要な場合にシンボル「END」が発生しました:(ループmodnullプラグマがreturnselect updateを発生させ、<<続行してclose current delete fetch lock insert open rollback savepoint setsqlexecutの場合にgotoのexitを宣言しますforallマージパイプパージをコミットします

4

1 に答える 1

0

前の質問と同様に、データの新しい行の特定の列を参照する場合は、:new疑似レコードを使用する必要があります。ですから、最低限、

SELECT cid 
  INTO c_id
  FROM transactions t
 WHERE t.aid = aid;

する必要があるだろう

SELECT cid 
  INTO c_id
  FROM transactions t
 WHERE t.aid = :new.aid;

さらに、行がtaletransactionsに挿入される前に、行がテーブルに存在することを確認しますか? 通常の外部キー制約があると仮定すると、行をテーブルに挿入する前にテーブルにaccounts行を挿入することが一般的に期待されます。 accountstransactions

名前transactionsもかなり奇妙に思えます。それが本当に顧客 ID をアカウント ID にマッピングするだけの場合はtransactions、かなり不適切な名前のように思えます。そのテーブルに実際にトランザクションが格納されている場合、なぜ顧客 ID が含まれているのかわかりません。ただし、トランザクションを保存する場合は、顧客をアカウントにマップする別のテーブルが必要です。

更新されたトリガーには、END IFステートメントがありません

CREATE OR REPLACE TRIGGER acc_opened
  BEFORE INSERT ON transactions
  FOR EACH ROW
DECLARE
  c_name customers.name%TYPE;
BEGIN
  IF :new.type = 'Open' 
  THEN
    SELECT name 
      into c_name
      FROM customers c
     WHERE c.cid = :new.cid;

     INSERT INTO logs (who, what) 
       VALUES (c_name, 'An account has been opened');
  END IF;
END;
于 2012-12-07T05:18:03.960 に答える