繁体   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