27

I need write insert or update trigger, but with WHEN condition with compare OLD and NEW rows.

According documentation OLD is null for insert operation. How i can use OLD in WHEN condition for INSERT AND UPDATE triggers?

Example trigger:

CREATE TRIGGER mytrigger
    BEFORE INSERT OR UPDATE ON "mytable"
    FOR EACH ROW 
    WHEN (NEW.score > 0 AND OLD.score <> NEW.score)
    EXECUTE PROCEDURE mytrigger();

but for insert OLD is null.

5
  • 1
    Could you show your code? Commented Mar 16, 2016 at 7:42
  • 2
    OLD.score IS NULL might be useful. Or you could have two separate triggers (that can still share the same procedure). Commented Mar 16, 2016 at 7:46
  • but according documentation postgres not garant execute operation order. For example OLD.score may be executed before OLD is null Commented Mar 16, 2016 at 7:47
  • 2
    INSERT trigger's WHEN condition cannot reference OLD values LINE 34: ...EW.score IS NOT NULL AND NEW.score <> '' AND (OLD.score. I need seperate on two trigger. Commented Mar 16, 2016 at 7:57
  • try to define when condition inside the mytrigger() Commented Mar 16, 2016 at 8:33

2 Answers 2

38

Option A:

You can change the code so that conditions will be in the trigger function rather than the trigger itself. With this approach OLD will be used only in the UPDATE.

Trigger:

CREATE TRIGGER mytrigger
    BEFORE INSERT OR UPDATE ON "mytable"
    FOR EACH ROW 
    EXECUTE PROCEDURE mytrigger();

Trigger function:

CREATE OR REPLACE FUNCTION mytrigger()
  RETURNS trigger AS
$BODY$
begin
if NEW.score > 0 then
     --code for Insert
     if  (TG_OP = 'INSERT') then
           YOUR CODE
     end if;

     --code for update
     if  (TG_OP = 'UPDATE') then
           if OLD.score <> NEW.score then  -- (if score can be null see @voytech comment to this post)
              YOUR CODE
           end if;
     end if;
end if;
return new;
end;
$BODY$
  LANGUAGE plpgsql VOLATILE

Option B:

As Thilo suggested write two triggers that share the same trigger function.

Triggers:

CREATE TRIGGER mytrigger1
    BEFORE INSERT ON "mytable"
    FOR EACH ROW 
    WHEN NEW.score > 0
    EXECUTE PROCEDURE mytrigger();


CREATE TRIGGER mytrigger2
    BEFORE UPDATE ON "mytable"
    FOR EACH ROW 
    WHEN (NEW.score > 0 AND OLD.score <> NEW.score)
    EXECUTE PROCEDURE mytrigger();

Trigger function:

CREATE OR REPLACE FUNCTION mytrigger()
  RETURNS trigger AS
$BODY$
begin
      YOUR CODE
return new;
end;
$BODY$
  LANGUAGE plpgsql VOLATILE
Sign up to request clarification or add additional context in comments.

4 Comments

Remember that NULL is not equal to NULL - so when comparing OLD.score with NEW.score it would be more wise to use IS DISTINCT FROM statement: OLD.score IS DISTINCT FROM NEW.score
@voytech I just copied his condition. We don't know what type score is. It can also be not null field. We can work only with the information that was provided :) In any case, I edited the code with reference to your comment.
But i want use went outside trigger for optimize
@Artemiy StagnantIce Alexeew See Option B
-2

Trigger.oldMap.keySet(); will give the Id's present in the Trigger.oldMap. It is a set type collection of all the Id's. have a look at the following example, change the DML events in the trigger events every time and see the debug logs. you will understand which trigger context variable is available for which DML event.

    CREATE TRIGGER Email_Check_On_Contact
                 before update{
     oldMap<ID,Contact>=new Map<ID,Contact>();
     o = trigger.oldMap;
     for(Contact newcont: trigger.new)
     {
        if(newcont.Email != o.get(newcont.Id).Email)
        {
            newcont.Email.addError('Email cannot be changed');
        }
      }
   }

2 Comments

This doesn't seem to be SQL or PL/pgSQL
This looks like syntax for Salesforce, which seems unhelpful in a question for Postgres.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.