zealmurugan
zealmurugan

Reputation: 329

How to use PostgreSQL triggers?

I am trying to use PostgreSQL triggers in my rails app. So I tried using this migration where execution of triggers is supposedly easy:

-- class AddTriggersToProducts < ActiveRecord::Migration
  def self.up
    table :products
    execute %q{
        create trigger trig1 before insert on products for each row
        begin 
        price = price + 5
        end;
        }
  end

  def self.down
    execute 'DROP TRIGGER trig1'
  end
end

But this didn't change anything. I don't know where to write the procedure or function if I am going to use one here ...

Upvotes: 4

Views: 4772

Answers (3)

Erwin Brandstetter
Erwin Brandstetter

Reputation: 656754

"Creating a trigger" consists of two steps in PostgreSQL:

1.) Create a trigger function - with special return value trigger:

CREATE FUNCTION trg_update_prod_price()
  RETURNS trigger AS
$func$
BEGIN
   NEW.price := NEW.price + 5;
   RETURN NEW;
END
$func$  LANGUAGE plpgsql;

Multiple triggers can use the same trigger function.

2.) Create a trigger calling an existing trigger function:

CREATE TRIGGER update_prod_price
BEFORE INSERT ON products
FOR EACH ROW EXECUTE PROCEDURE trg_update_prod_price();

To "drop the trigger" (meaning the trigger function), you have to first drop all triggers referencing it and then drop the trigger function itself.

DROP TRIGGER update_prod_price ON products;
DROP FUNCTION trg_update_prod_price();

If you drop a table, all attached triggers are dropped with it. No need to drop those separately.

Upvotes: 10

Justin Tanner
Justin Tanner

Reputation: 14352

The hair_trigger gem is a nice way to manage the creation of triggers.

Here is an example from hair_trigger's docs:

class AccountUser < ActiveRecord::Base
  trigger.after(:insert) do
    "UPDATE accounts SET user_count = user_count + 1 WHERE id = NEW.account_id;"
  end

  trigger.after(:update).of(:name) do
    "INSERT INTO user_changes(id, name) VALUES(NEW.id, NEW.name);"
  end
end

Upvotes: 2

njorden
njorden

Reputation: 2606

Does something like this work? Creating a function and then executing the function for the trigger:

   def self.up 
     execute %q{
       create or replace function update_price() returns trigger as $$
         begin
           NEW.price := NEW.price + 5;
           return NEW;
         end;
       $$ language plpgsql }

      execute %{ create trigger trig1 before insert on products for each row execute function update_price()}
  end

Upvotes: 2

Related Questions