简体   繁体   中英

Postgres Syntax Error - Triggers

I am using Triggers, cases and Exists for the first time, and cannot figure out the problem. I have replaced the table names are attributes for the responder's convenience.

Essentially, what I want is that: When I insert an entry to my temporal table,

  • if the new entry's primary key already exists in the temporal table, I want this new entry's start date to be the previous record's end date.

  • if the new entry is completely new to the table, nothing happens (the insert operates as usual).

The code is:

CREATE OR REPLACE FUNCTION update_End_Date()
  RETURNS trigger AS
$$
BEGIN 

    SELECT CASE
    WHEN EXISTS ( SELECT TemporalTable.primaryKey FROM TemporalTable WHERE primaryKey =  NEW.primaryKey )
    THEN 
      UPDATE 
          TemporalTable
     SET 
        TemporalTable.DtEnd = NEW.DtStart
    WHERE
        TemporalTable.PrimaryKey = NEW.PrimaryKey AND 
        TemporalTable.DtEnd IS NULL
        ;  
    END

    RETURN NEW; 
RETURN NEW;
END;

$$
LANGUAGE 'plpgsql';


CREATE TRIGGER update_End_Date
  BEFORE INSERT  
  ON Table1 
  FOR EACH ROW  
  EXECUTE PROCEDURE update_End_Date(); 

You have a conceptual error with regards to the use of the CASE clause in a SELECT statement: you evaluate some condition to produce an output for the select list. Instead you use it as a logic branch operation as you would in a procedural language like C . Since a trigger is always written in the plpgsql procedural language you can easily rewrite the trigger function as follows:

CREATE OR REPLACE FUNCTION update_End_Date() RETURNS trigger AS $$
BEGIN 
    PERFORM * FROM TemporalTable WHERE primaryKey = NEW.primaryKey;
    IF FOUND THEN 
        UPDATE TemporalTable
        SET DtEnd = NEW.DtStart
        WHERE PrimaryKey = NEW.PrimaryKey AND DtEnd IS NULL;  
    END IF;
    RETURN NEW; 
END;
$$ LANGUAGE plpgsql;

The PERFORM command checks if some data is present without returning any data and sets the FOUND implicit variable to true or false which you can then check.

But if this is all the logic in your trigger function (ie there are no parts which you do not show here) you can simply leave out the check and do a straight UPDATE : if a record is not there for updating then nothing happens and the trigger function simply continues:

CREATE OR REPLACE FUNCTION update_End_Date() RETURNS trigger AS $$
BEGIN 
    UPDATE TemporalTable
    SET DtEnd = NEW.DtStart
    WHERE PrimaryKey = NEW.PrimaryKey AND DtEnd IS NULL;  
    RETURN NEW; 
END;
$$ LANGUAGE plpgsql;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM