INSERT Trigger to check for existing records

From: Hagen Finley <hagen(at)datasundae(dot)com>
To: pgsql-general(at)lists(dot)postgresql(dot)org
Subject: INSERT Trigger to check for existing records
Date: 2020-11-21 16:00:23
Message-ID: 3e1051a4-98d4-4a59-f382-5b82efa4c095@datasundae.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Hello,

I am definitely out over my skis here so I’ll apologize in advance 😉.
Running version 12.5-1.pgdg20.04+1 on ubuntu. It’s essentially a
personal database I use to ingest sales forecast spreadsheets from which
I  create custom reports for my job function.

I pull a new forecast spreadsheet each Monday. 80% of the records are
the same as the existing records from the week before.

Here’s what I (REALLY) want:

Trigger looks at three fields prior to new insert: Deal ID (numeric),
revenue (numeric), stage(char)     Example: 19743576 22072.37    Commit
- 90%

1. If the NEW dealid doesn't match any of the OLD dealids, insert the
new row
2. if the NEW dealid, revenue and stage fields ALL match the OLD
dealid, revenue and stage, skip (don't insert the NEW row)
3. If the NEW dealid matches an OLD dealid but either the NEW revenue
OR the stage fields have changed (don't match OLD record) insert new
row (I'll review both rows manually)

*Attempt 1: *Update chk field with 'same' if OLD revusd OR stage are
different than the NEW revusd OR stage

CREATE TRIGGER chk4chg
BEFORE
    INSERT ON sfdc
    FOR EACH ROW
BEGIN
    UPDATE sfdc
    SET chk = 'same'
    WHERE ndealid = :NEW.ndealid
      AND revusd = :NEW.revusd
      AND stage = :NEW.stage
END chk4chg;

Remarkably, that works in that it will UPDATE the chk field with 'same'

|ndealid |revusd |stage                 |chk       |

|17713063|1300000|Propose - 60%         |same      |

However, I must manually enter the parameters in dialogue box that
(inexplicably) pops up when I run this command.

*Attempt 2:*

CREATE OR REPLACE FUNCTION update_insert() RETURNS trigger AS $$
BEGIN
    UPDATE sfdc
    SET chk = 'same'
    WHERE ndealid = OLD.ndealid;
    AND NEW.revusd = OLD.revusd
    AND NEW.stage = OLD.stage;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE FUNCTION Query returned successfully in 136 msec.

That's good news but the trigger doesn't actually update. It lacks
BEFORE INSERT ON sfdc FOR EACH ROW so low prospect for success :-).

*Attempt 3: *A little more sophisticated executing Function from Trigger

CREATE TRIGGER smart_update_same BEFORE INSERT ON sfdc
FOR EACH ROW EXECUTE FUNCTION update_insert();

CREATE OR REPLACE FUNCTION update_insert() RETURNS trigger AS $$
BEGIN
    UPDATE sfdc
    SET sfdc.chk = 'same'
    WHERE NEW.ndealid = OLD.ndealid
      AND NEW.revusd = OLD.revusd
      AND NEW.stage = OLD.stage;
END;
$$ LANGUAGE plpgsql;

These 2 CREATEs return successfully but do not update the chk field on a
successful INSERT:

sales=# select ndealid,revusd,stage,chk from sfdc where ndealid = 19743576;

  ndealid   |  revusd  |         stage          | chk

 19743576 | 22072.37 | Commit - 90%           |
   19743576 | 22072.37 | Commit - 90%           |
   19743576 | 22072.37 | Commit - 90%           |

These 3 attempts won't give me what I REALLY want but I figure I could
use the chk field to delete the new inserts I didn't need.

Am I anywhere close (same county) to the right code?

Hagen

Larimer County, CO

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message David G. Johnston 2020-11-21 16:15:43 Re: INSERT Trigger to check for existing records
Previous Message Luca Ferrari 2020-11-21 15:34:14 Re: two questions about toast