复合触发器:将变异行收集到嵌套表中

时间:2014-01-28 23:36:15

标签: sql oracle triggers oracle11g

我的项目中有两个表:帐户和事务(一对多关系)。在每个交易中,我存储相关账户的余额(在执行交易之后)。此外,在每个交易中,我都存储了交易的价值。

所以当有人添加新事务时我需要触发一个触发器。它应检查新帐户余额是否正确(旧帐户余额+交易价值=存储在交易中的新帐户余额)。

所以我被建议,我应该使用复合触发器:

  • 在每个行部分之前:在某处保存行的PK(由两列组成),
  • 在after语句部分:检查所有插入的事务是否正确。

现在我找不到任何地方如何实现第一点。

我已经拥有的东西:

CREATE OR REPLACE TRIGGER check_account_balance_is_valid
FOR INSERT
ON Transactions
COMPOUND TRIGGER
  TYPE Modified_transactions_T IS TABLE OF Transactions%ROWTYPE;
  Modified_transactions       Modified_transactions_T;

  BEFORE STATEMENT IS BEGIN
    Modified_transactions := Modified_transactions_T();
  END BEFORE STATEMENT;

  BEFORE EACH ROW IS BEGIN
    Modified_transactions.extend;
    Modified_transactions(Modified_transactions.last) := :NEW;
  END BEFORE EACH ROW;

  AFTER STATEMENT IS BEGIN
    NULL; -- I will write something here later
  END AFTER STATEMENT;
END check_account_balance_is_valid;
/

然而,我得到了: 警告:执行完成并发出警告 11/58 PLS-00049:错误的绑定变量'NEW'

有人能告诉我,如何修复它?或者也许我的整个“复合触发”想法是错误的,你有更好的建议。

更新1

这是我的ddl脚本:http://pastebin.com/MW0Eqf9J

2 个答案:

答案 0 :(得分:1)

也许试试这个:

TYPE Modified_transactions_T IS TABLE OF ROWID;
Modified_transactions       Modified_transactions_T;

BEFORE STATEMENT IS BEGIN
  Modified_transactions := Modified_transactions_T();
END BEFORE STATEMENT;

BEFORE EACH ROW IS BEGIN
  Modified_transactions.extend;
  Modified_transactions(Modified_transactions.last) := :NEW.ROWID;
END BEFORE EACH ROW;

或者

TYPE PrimaryKeyRecType IS RECORD (
   Col1 Transactions.PK_COL_1%TYPE, Col2 Transactions.PK_COL_2%TYPE);
TYPE Modified_transactions_T IS TABLE OF PrimaryKeyRecType;

...

Modified_transactions(Modified_transactions.last) := PrimaryKeyRecType(:NEW.PK_COL_1, :NEW.PK_COL_2);

答案 1 :(得分:0)

您当前的问题是:new不是真实记录,因此它不是Transactions%ROWTYPE类型。如果你真的想沿着这条路走下去,你通常会想要声明一个表的主键集合

TYPE Modified_transactions_T IS TABLE OF Transactions.Primary_Key%TYPE;

然后只将主键放在集合

BEFORE EACH ROW IS BEGIN
    Modified_transactions.extend;
    Modified_transactions(Modified_transactions.last) := :NEW.Primary_Key;
  END BEFORE EACH ROW;

然而,您首先尝试解决变异表异常这一事实几乎总是表明您有一个您应该真正解决的基础数据建模问题。如果您需要查询表中的其他行以便弄清楚要对新行执行的操作,那么这是一个非常好的迹象,表明您对数据模型进行了不正确的规范化,并且一行依赖于另一行。相同的表而不是一个自治的事实。修复数据模型几乎总是更适合处理变异表异常。