PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

INSERT eine reelle Zahl in eine Spalte basierend auf anderen Spalten OLD INSERTs

Basierend auf den ersten beiden Anforderungen ist an Ihrem Trigger an sich nichts auszusetzen, aber Sie können ihn stark vereinfachen:

CREATE OR REPLACE FUNCTION timelog() RETURNS trigger AS $BODY$
DECLARE
  t_ix real;
BEGIN
  -- First check if you need to change NEW at all
  IF (NEW.time_type = 'Start') OR (NEW.time_type = 'Lap') THEN
    -- Now perform the expensive lookup for either of 'Start' or 'Lap'
    SELECT time_index INTO t_ix
    FROM table_ebscb_spa_log04
    WHERE fn_name = NEW.fn_name
      AND (time_type = 'Start' OR time_type = 'Lap')
    ORDER BY stmtserial DESC LIMIT 1;

    IF NOT FOUND THEN
      -- Nothing found, so NEW.time_index := 1
      NEW.time_index := 1; 
    ELSIF NEW.time_type = 'Start' THEN 
      -- Start new index for fn_name, discard any fractional part, then increment
      NEW.time_index := floor(t_ix) + 1; 
    ELSE
      -- Continue the lap, increment NEW.time_index
      NEW.time_index := t_ix + 0.1; 
    END IF;
  END IF;
  RETURN NEW;
END; $BODY$ LANGUAGE plpgsql;

Es gibt jedoch einen viel einfacheren Weg, der auch die dritte Anforderung problemlos erfüllt. Anstatt auf die „time_index“-Werte zu schauen, sollten Sie sich den „time“-Wert ansehen, denn darauf basiert „time_index“:

CREATE OR REPLACE FUNCTION timelog() RETURNS trigger AS $BODY$
DECLARE
  t_ix real;
BEGIN
  -- Find the most recent entry for the same "fn_name" as the new record
  SELECT time_index INTO t_ix
  FROM table_ebscb_spa_log04
  WHERE fn_name = NEW.fn_name
  ORDER BY time DESC LIMIT 1;

  -- Nothing found, so NEW.time_index := 1
  IF NOT FOUND THEN
    NEW.time_index := 1;
    RETURN NEW;
  END IF;

  -- Some record exists, so update "time_index" based on previous record
  CASE NEW.time_type 
    WHEN 'Start' THEN 
      -- Start new index for fn_name, discard any fractional part, then increment
      NEW.time_index := floor(t_ix) + 1; 
    WHEN 'Lap' THEN
      -- Continue the lap, increment NEW.time_index
      NEW.time_index := t_ix + 0.1; 
    ELSE
      -- Break, find previous break or start, increment by 0.1
      SELECT time_index + 0.1 INTO NEW.time_index
      FROM table_ebscb_spa_log04
      WHERE fn_name = NEW.fn_name
        AND (time_type = 'Start' OR time_type = 'Break')
      ORDER BY time DESC LIMIT 1;
  END CASE;

  RETURN NEW;
END; $BODY$ LANGUAGE plpgsql;

Dies implementiert Ihre Logik, aber beachten Sie, dass es einige potenzielle Fallstricke gibt:

  • Was passiert, wenn Sie vor einem "Start" eine "Runde" oder eine "Pause" einfügen?
  • Was ist, wenn Sie mehr als 9 „fn_name“-Ereignisse nach einem „Start“ haben („time_index“-Bruchteil wird auf die nächste Ganzzahl übertragen)?

Sie könnten natürlich das "time_index"-Feld und den Trigger ganz vergessen und ihn spontan in einer Ansicht generieren, wenn Ihr Datenmodell dies zulässt (dasselbe gilt für "time_elapse").