如何在PostgreSQL中编写触发器以将字段与另一个表中的字段进行比较

时间:2011-04-23 11:10:40

标签: sql database postgresql triggers plpgsql

这是我第一次尝试触发器。我已经理解了触发器背后的概念和用法,但是我不太清楚如何编写程序。

基本上我有一个表,我们称之为'Money',它有一个名为'Max_transaction_amount'的字段,另一个字段叫做'Currency_ID'然后,我有一个名为'Transactions'的表。基本上,我想要实现的是一种机制,无论何时将新交易添加到“交易”表中,都会进行检查以查看与某种货币相关的所有交易的“计数”是否超过'名为“Money”的表中的Max_transaction_amount',与'Currency_ID'相关。

对于有数据库经验的用户来说,这似乎是一个非常简单的问题,但我仍然在学习,并希望编写这样的程序,以便从右脚开始。

不幸的是我无法提供任何代码,因为我没有丝毫的线索知道我将如何做到这一点。但是,这是我认为可能有效的方法:

  • 触发器需要在更新“交易”表时执行
  • 该过程通过检查其“Currency_ID”来检查正在添加的记录中的“Max_transaction_amount”。
  • 执行select语句以查找符合特定“Currency_ID”
  • 的行数
  • 将检查'Money'表中的'Max_transaction_amount'字段,以查看该特定货币的最高金额
  • 在“交易”表格中,将与该特定货币相关的所有记录的计数与“max_transaction_amount”进行比较
  • 如果小于或等于最大金额,则保存更改。

非常感谢任何帮助!


我尝试编写以下程序...虽然接受了语法,但如果我试图超过金额,则没有任何反应。有人可以指导我朝正确的方向发展吗?

BEGIN

IF ((SELECT COUNT(Currency_ID) FROM "Transactions" WHERE "Currency_ID" = NEW.Currency_ID) > (SELECT "max_transaction_amount" FROM "Money" WHERE "Currency_ID" = NEW.Currency_ID)) THEN
RAISE EXCEPTION 'Error';

END IF;
END;

1 个答案:

答案 0 :(得分:2)

不确定我是否理解了max_transaction_amount的存储方式,但对我而言,听起来你可以通过moneys表中的balance列和check约束来实现这一点。每次将一行插入到交易表

中时,余额就会更新
CREATE TABLE money 
(
   currency_id              integer not null,
   max_transaction_amount   numeric(18,2) not null,
   current_balance          numeric(18,2) not null default 0,
   primary key (currency_id),
   check (current_balance <= max_transaction_amount)
);

CREATE TABLE transactions 
(
  transaction_id       integer not null,
  transaction_amount   numeric(18,2) not null,
  currency_id          integer not null,
  primary key (transaction_id),
  foreign key (currency_id) references money (currency_id)
);

现在,您只需要确保每次插入事务时都更新current_balance。这似乎是规则有意义的罕见情况之一(但也可以在触发器中完成 - 特别是如果您需要进行更多检查):

CREATE RULE transactions_insert AS 
  ON INSERT TO transactions
    DO UPDATE money 
          SET current_balance = current_balance + new.transaction_amount
       WHERE currency_id = new.currency_id;

现在,在更新current_balance列时,检查约束将确保未超出max_transaction_amount

如果您需要将UPDATE覆盖到表中,则需要创建另一个规则:

CREATE RULE transactions_update AS 
  ON UPDATE TO transactions
    DO UPDATE money 
          SET current_balance = current_balance - old.transaction_amount + new.transaction_amount
       WHERE currency_id = new.currency_id;

当然,这两条规则也可以通过一个触发功能来完成。