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”:(如果使用<<继续关闭当前删除获取锁定插入打开,则开始情况声明退出goto如果loop mod null pragma raise返回选择更新rollback savepoint set sql execut commit forall merge pipe purge
答案 0 :(得分:0)
与previous question一样,如果要引用新行数据的特定列,则需要使用: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;
除此之外,在将行插入transactions
故事之前,您确定该行存在于accounts
表中吗?假设您有正常的外键约束,我通常希望在将行插入accounts
表之前将行插入transactions
表。
名称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;