Dựa trên hai yêu cầu đầu tiên, không có gì sai với trình kích hoạt của bạn, nhưng bạn có thể đơn giản hóa nó rất nhiều:
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;
Tuy nhiên, có một cách dễ dàng hơn nhiều và điều đó cũng sẽ đáp ứng được yêu cầu thứ ba mà không có vấn đề gì. Thay vì xem xét các giá trị "time_index", bạn nên xem xét giá trị "time", vì đó là những gì "time_index" dựa trên:
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;
Điều này thực hiện logic của bạn nhưng lưu ý rằng có một số cạm bẫy tiềm ẩn:
- Điều gì sẽ xảy ra nếu bạn chèn 'Vòng quay' hoặc 'Ngắt' trước 'Bắt đầu'?
- Điều gì sẽ xảy ra nếu bạn có hơn 9 sự kiện "fn_name" sau 'Start' (phần phân số "time_index" sẽ chuyển sang số nguyên tiếp theo)?
Tất nhiên, bạn có thể quên hoàn toàn trường "time_index" và trình kích hoạt và tạo nó ngay lập tức trong một chế độ xem, nếu mô hình dữ liệu của bạn cho phép nó (tương tự với "time_elapse").