sql >> Database >  >> RDS >> PostgreSQL

VOEG een reëel getal in een kolom in op basis van andere kolommen OUDE INSERT's

Op basis van de eerste twee vereisten is er op zich niets mis met je trigger, maar je kunt het enorm vereenvoudigen:

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;

Er is echter een veel eenvoudigere manier en die zal ook probleemloos aan de derde eis voldoen. In plaats van naar de "time_index"-waarden te kijken, zou u naar de "time"-waarde moeten kijken, want daar is "time_index" op gebaseerd:

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;

Dit implementeert uw logica, maar houd er rekening mee dat er enkele potentiële valkuilen zijn:

  • Wat als je een 'Ronde' of een 'Pauze' invoegt voor een 'Start'?
  • Wat als je meer dan 9 'fn_name'-gebeurtenissen hebt na een 'Start' ('time_index'-breukje gaat over naar het volgende gehele getal)?

U kunt natuurlijk het veld "time_index" en de trigger helemaal vergeten en het direct in een weergave genereren, als uw gegevensmodel dit toestaat (hetzelfde met "time_elapse").




  1. Hoe kan ik Arabische tekst uit de MySQL-database naar csv exporteren met Toad voor MySQL?

  2. Hoe tel ik alleen het eerste voorkomen van een waarde?

  3. Hoe EXISTS Logical Operator te gebruiken in SQL Server - SQL Server / TSQL Tutorial Part 125

  4. Wat zijn realtime-apps?