0

Basically I have table_a and table_b. table_b is made with features from table_a and in common they share section_id column and status.

table_a's section_id is primary key so it's unique, but table_b can have multiple section_ids, but they all share same status

Users insert and update table_b and I want to capture the status changes back in table_a

CREATE TRIGGER table_b_aiu
AFTER INSERT OR UPDATE
ON table_b
FOR EACH ROW
WHEN (((new.status = 100) OR (new.status = 200)))
EXECUTE PROCEDURE table_b_aiu();

CREATE OR REPLACE FUNCTION table_b_aiu()
RETURNS trigger AS
$BODY$
BEGIN
UPDATE table_a a
SET status = 100
FROM table_b b
WHERE (b.status = 100 or b.status = 200) 
AND a.section_id = b.section_id;
    RETURN new; 
END;
$BODY$
 LANGUAGE plpgsql VOLATILE
 COST 100;

The problem with this, is that instead of updating just the newly updated or inserted row, it updates the ENTIRE dataset, which is not intended. How to update only new rows? I've tried putting arguments on the triger but it doesn't accept new.section_id

  • 1
    IMHO you should pass new.section_id as a parameter of table_b_aiu() and use it on where clause. – McNets Aug 4 '17 at 12:41
  • has nothing to do with PostGIS. Can you dump your schema, \d table_b, \d table_a – Evan Carroll Aug 8 '17 at 21:58
3

By default, UPDATE table_a ... FROM table_b builds CROSS JOIN of all rows from both tables. So such UPDATE applies to all rows of table_a.

Solution is simple: add to WHERE condition

AND a.section_id = NEW.section_id

to limit rows of CROSS JOIN result to only just-now-updated rows.

NEW and OLD are a system record which keep values of all columns of row for which trigger function has been called.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.