PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

WSTAW liczbę rzeczywistą w kolumnie opartej na innych kolumnach OLD INSERT

W oparciu o pierwsze dwa wymagania nie ma nic złego w wyzwalaczu per se, ale można go znacznie uprościć:

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;

Jest jednak o wiele prostszy sposób, który bez problemu spełni również trzecie wymaganie. Zamiast patrzeć na wartości „time_index”, powinieneś spojrzeć na wartość „time”, ponieważ na tym opiera się „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;

To implementuje twoją logikę, ale pamiętaj, że istnieją pewne potencjalne pułapki:

  • Co się stanie, jeśli wstawisz „Okrążenie” lub „Przerwę” przed „Startem”?
  • Co zrobić, jeśli masz więcej niż 9 zdarzeń „fn_name” po „Start” (część ułamkowa „time_index” zostanie przeniesiona do następnej liczby całkowitej)?

Możesz oczywiście całkowicie zapomnieć o polu „time_index” i wyzwalaczu i wygenerować je na bieżąco w widoku, jeśli Twój model danych na to pozwala (to samo z „time_elapse”).




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Rozwiązanie przyspieszające powolne zapytanie SELECT DISTINCT w Postgres

  2. Uśpienie komety PHP blokuje apache mpm?

  3. pg_stat_activity nie aktualizuje się w ramach procedury lub transakcji

  4. Musisz dynamicznie wybrać element tablicy JSON z tabeli postgresql

  5. Zapytanie postgres jsonb według wartości niezależnie od kluczy