Как написать триггер в PostgreSQL для сравнения поля с полем в другой таблице - PullRequest
0 голосов
/ 23 апреля 2011

Я впервые пробую триггер.Я понял концепцию и использование триггеров, однако я не очень уверен, как написать процедуру.

В основном у меня есть таблица, которую мы назовем «Деньги», котораяимеет поле с именем «Max_transaction_amount» и другое поле с именем «Currency_ID». Затем у меня есть таблица с именем «транзакции».По сути, я хочу добиться механизма, при котором при добавлении новой транзакции в таблицу «Транзакции» выполняется проверка, чтобы убедиться, что «Счет» всех транзакций, относящихся к определенной валюте, не превышаетMax_transaction_amount 'в таблице с именем' Money 'относительно' Currency_ID '.

Это кажется очень простой проблемой для пользователей, имеющих опыт работы с базами данных, однако я все еще учусь и хотел бы написать такуюПроцедура, чтобы начать с правой ноги.

К сожалению, я не могу предоставить какой-либо код, потому что я не имею ни малейшего понятия о том, как я собираюсь сделать это.Однако, это то, что я «думаю» может работать:

  • Триггер должен будет выполняться при обновлении таблицы «Транзакции»
  • Процедура проверяет «Max_transaction_amount» взапись, которая добавляется, путем проверки ее «Currency_ID».
  • Оператор выбора выполняется, чтобы найти количество строк, соответствующих этому конкретному «Currency_ID»
  • Поле «Max_transaction_amount» втаблица «Деньги» будет проверена, чтобы увидеть, какова максимальная сумма для данной конкретной валюты
  • В таблице «Транзакции» количество всех записей, относящихся к этой конкретной валюте, сравнивается с «max_transaction_amount»
  • Если она меньше или равна максимальной сумме, изменения сохраняются.

Любая помощь будет принята с благодарностью!


Iя пытался написать следующую процедуру ... пока синтаксис принят, ничего не происходит, если я пытаюсь превысить сумму.Кто-нибудь может направить меня в правильном направлении?

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 Ответ

2 голосов
/ 24 апреля 2011

Не уверен, что я понял, как хранится max_transaction_amount, но для меня это звучит так, как будто вы можете достичь этого с помощью столбца баланса в таблице денежных средств и проверочного ограничения. Баланс будет обновляться каждый раз, когда в таблицу транзакций вставляется строка

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 s к таблице, вам нужно создать другое правило:

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;

Конечно, эти два правила могут быть выполнены и с одной триггерной функцией.

...