sql >> Database teknologi >  >> RDS >> PostgreSQL

INDSÆT et reelt tal i en kolonne baseret på andre kolonner GAMLE INDSÆT

Baseret på de to første krav er der ikke noget galt med din trigger i sig selv, men du kan forenkle det meget:

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;

Der er dog en meget nemmere måde, og det vil også imødekomme det tredje krav uden problemer. I stedet for at se på "time_index" værdierne, bør du se på "time" værdien, fordi det er det "time_index" er baseret på:

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;

Dette implementerer din logik, men bemærk, at der er nogle potentielle faldgruber:

  • Hvad hvis du indsætter en 'Omgang' eller en 'Pause' før en 'Start'?
  • Hvad hvis du har mere end 9 "fn_name"-begivenheder efter en 'Start' ("time_index"-brøkdel vil rulle over til det næste heltal)?

Du kan selvfølgelig glemme "time_index"-feltet og triggeren helt og generere det på farten i en visning, hvis din datamodel tillader det (samme med "time_elapse").




  1. mysql_real_escape_string() fjerner streng fuldstændigt

  2. Indekseret BESTIL AF med LIMIT 1

  3. Forstå forskellen mellem EXCEPT og NOT IN-operatører

  4. Konverter IP-adresse (IPv4) uden et heltal i R