簡體   English   中英

Function 和 postgresql 的觸發器在一個表中更新另一個表中發生的更改

[英]Function and trigger of postgresql to update in a table the changes that take place in another one

我需要創建一個 tg_athletes_info 觸發器,該觸發器在每行插入、刪除或更新 REGISTER 表 (tb_register) 的每一行時執行 fn_athletes_info function。 新的 function,fn_athletes_info,必須插入或更新表 tb_athletes_info_log 表所需的信息,或刪除它以防已從 REGISTER 表(tb_register)中刪除。 表(tb_register)。 為了對 tb_athletes_info_log 表執行任何操作,function 將從表中獲取所有必要的信息:REGISTER (tb_register)、ATHLETE (tb_athlete) 和 DISCIPLINE (tb_discipline)。

運動員的標記屬性(tb_athletes_info_log 表的標記)將存儲 tb_register 表的以下兩個屬性之一的非空值:register_time 屬性的值或 register_measure 屬性的值。

運動員的標記屬性(來自 tb_athletes_info_log 表的標記)必須包含 12 個可變字符的字符串。 12 個可變字符的字符串。

因此,需要將非空屬性值(register_time 或 register_measure)的類型轉換為字符串。

我認為由於 register_time 是 date 類型,而 register_measure 是 integer 類型,並且表 tb_athletes_info_log 的標記是 varchard,因此應該使用 to_char 進行更改。 另一方面,我認為還需要實現一個 if 條件,以便如果 register_time 是 NULL,則 mark 取 register_measure 的值,反之亦然,因為這個 mark 字段不能有 null 值。

表格如下:


CREATE TABLE olympic.tb_register (
  athlete_id    CHARACTER(7) NOT NULL,
  round_number  INT NOT NULL,
  discipline_id INT NOT NULL,
  register_date  DATE NOT NULL DEFAULT CURRENT_DATE,
  register_position INT DEFAULT NULL,
  register_time     TIME DEFAULT NULL,
  register_measure  REAL DEFAULT NULL,
  CONSTRAINT pk_register PRIMARY KEY (athlete_id, round_number, discipline_id),
  CONSTRAINT fk_register_athlete FOREIGN KEY (athlete_id) REFERENCES olympic.tb_athlete (athlete_id),
  CONSTRAINT fk_register_round FOREIGN KEY (discipline_id, round_number) REFERENCES olympic.tb_round (discipline_id, round_number)
);


CREATE TABLE olympic.tb_athlete    (
  athlete_id    CHARACTER(7) NOT NULL,
  name          CHARACTER VARYING(50) NOT NULL,
  country       CHARACTER VARYING(3) NOT NULL,
  substitute_id  CHARACTER(7) DEFAULT NULL,
  CONSTRAINT pk_athlete PRIMARY KEY (athlete_id),
  CONSTRAINT fk_athlete_substitute FOREIGN KEY (substitute_id) REFERENCES olympic.tb_athlete (athlete_id)
);

CREATE TABLE olympic.tb_discipline  (
  discipline_id  INT NOT NULL,
  name           CHARACTER VARYING(50) NOT NULL,
  inventor       CHARACTER VARYING(50) NOT NULL,
  type           CHARACTER VARYING(10) NOT NULL,
  object_type    CHARACTER VARYING(20) DEFAULT NULL, 
  CONSTRAINT ck_discipline_type CHECK (type IN ('RUN', 'JUMP', 'THROW')),
  CONSTRAINT pk_discipline PRIMARY KEY (discipline_id)
);

CREATE TABLE IF NOT EXISTS olympic.tb_athletes_info_log (
    athlete_id character(7) NOT NULL,
    discipline_id integer NOT NULL,
    round_number integer NOT NULL,
    athlete_name character varying(50) NOT NULL,
    discipline_name character varying(50) NOT NULL,
    mark character varying(12) NOT NULL,
    rating integer NOT NULL,
    info_log_dt date,
    CONSTRAINT pk_athlete_discipline_round PRIMARY KEY (athlete_id, discipline_id, round_number),
    CONSTRAINT fk_athlete_discipline_round FOREIGN KEY (athlete_id, discipline_id, round_number) REFERENCES olympic.tb_register(athlete_id, discipline_id, round_number)
);


以便:



athlete_id= tb_register.athlete_id
discipline_id=tb_register.discipline_id
round_number=tb_register.round_number
athlete_name=tb_athlete.name
discipline_name=tb_discipline.name
mark=tb_register.register_measure/tb_register.register_time
rating=tb_register.register_position
info_log_dt=tb_register.register_date

誰能提供有關如何將所有這些要求轉換為觸發器 function 的任何想法?

非常感謝您提前

您必須為插入、更新、刪除創建三個不同的觸發器。 觸發器DELETE ON可以替換為添加到fk_athlete_discipline_round FOREIGN KEY定義中的ON DELETE CASCADE

CREATE OR REPLACE FUNCTION fn_athletes_info_insert()
RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
INSERT INTO olympic.tb_athletes_info_log (athlete_id,discipline_id,round_number,athlete_name,discipline_name,mark,rating,info_log_dt)
SELECT NEW.athlete_id,NEW.discipline_id,NEW.round_number, a.name, d.name, COALESCE(NEW.register_time :: text, NEW.register_measure :: text),NEW.register_position,NEW.register_date
  FROM olympic.tb_athlete AS a
 CROSS JOIN olympic.tb_discipline AS d
 WHERE a.athlete_id = NEW.athlete_id
   AND d.discipline_id = NEW.discipline_id ;
RETURN NEW ;
END ;
$$ ;

CREATE TRIGGER tg_athletes_info_insert AFTER INSERT ON olympic.tb_register
FOR EACH ROW EXECUTE PROCEDURE fn_athletes_info_insert () ;

CREATE OR REPLACE FUNCTION fn_athletes_info_update()
RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
UPDATE olympic.tb_athletes_info_log
   SET athlete_id = NEW.athlete_id
     , discipline_id = NEW.round_number
     , round_number = NEW.discipline_id
     , athlete_name = a.name
     , discipline_name = d.name
     , mark = COALESCE(NEW.register_time :: text, NEW.register_measure :: text)
     , rating = NEW.register_position
     , info_log_dt = NEW.register_date
  FROM olympic.tb_athlete AS a
 CROSS JOIN olympic.tb_discipline AS d
 WHERE a.athlete_id = OLD.athlete_id
   AND d.discipline_id = OLD.discipline_id ;
RETURN NEW ;
END ;
$$ ;

-- trigger DELETE ON can be replaced by the ON DELETE CASCADE clause added to the fk_athlete_discipline_round FOREIGN KEY definition
CREATE TRIGGER tg_athletes_info_update AFTER UPDATE ON olympic.tb_register
FOR EACH ROW EXECUTE PROCEDURE fn_athletes_info_update () ;

CREATE OR REPLACE FUNCTION fn_athletes_info_delete ()
RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
DELETE FROM olympic.tb_athletes_info_log
WHERE athlete_id = OLD.athlete_id
  AND discipline_id = OLD.discipline_id
  AND round_number = OLD.round_number ;
RETURN OLD ;
END ;
$$ ;

CREATE TRIGGER tg_athletes_info_delete AFTER DELETE ON olympic.tb_register
FOR EACH ROW EXECUTE PROCEDURE fn_athletes_info_delete () ;

小提琴手

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM