繁体   English   中英

postgresql 触发器将倒数第三个字符与属性进行比较

[英]postgresql trigger to compare the third to last character with an attribute

我最近开始研究 PostgreSQL 并且在创建触发器时遇到了麻烦。 在特定情况下,我应该检查男性运动员不能参加女子比赛,反之亦然; 在 match_code 属性中,插入“M”或“F”作为倒数第三个字符,以标识比赛是针对男性还是女性(例如:“Q100x4M06”); 性别属性中只存储一个字符“M”或“F”。 因此,我需要了解如何比较它们并在它们未正确输入参与表时激活触发器。 这是我的假设,但我知道这是错误的,这只是一个想法,有人可以帮助我吗?

CREATE FUNCTION check()
RETURNS TRIGGER
LANGUAGE PLPGSQL
AS $BODY$
DECLARE
    x VARCHAR;
    y VARCHAR;
BEGIN
    SELECT match_code INTO x FROM race;
    SELECT gender INTO y FROM athlete;
    IF $x LIKE '&$y__' == athlete.gender
        THEN
        RETURN new;
    ELSE
        RAISE EXCEPTION $$It is not possible to add an athlete of a gender that is not compatible with the competition$$;
        RETURN NULL;
    END IF;
END;
$BODY$
CREAT TRIGGER triggerCheck
BEFORE INSERT OR UPDATE ON participation
FOR EACH ROW
EXECUTE PROCEDURE check();

以下是表格的定义:

CREATE TABLE race (
    ID_g SERIAL NOT NULL,
    code_race VARCHAR (20) PRIMARY KEY,
    r_date DATE,
    discipline VARCHAR (20) NOT NULL
);

CREATE TABLE athlete (
    ID_a SERIAL NOT NULL,
    code_athlete INT CHECK (codice_atleta >= 0 AND codice_atleta <= 15000) PRIMARY KEY,
    name VARCHAR (30),
    surname VARCHAR (30) NOT NULL,
    nation VARCHAR (3) NOT NULL,
    gender CHAR CHECK (gender = 'M' OR gender = 'F'),
    b_date DATE,
    sponsor VARCHAR (20)
);

CREATE TABLE participation (
    ID_p SERIAL NOT NULL,
    codR VARCHAR (20) REFERENCES race (code_race) ON DELETE CASCADE ON UPDATE CASCADE,
    codA INT REFERENCES athlete (code_athlete) ON DELETE CASCADE ON UPDATE CASCADE,
    arrival_order INT CHECK (arrival_order > 0),
    r_time TIME DEFAULT '00:00:00.00',
    PRIMARY KEY (codG, codA)
);

根据表格定义,您的触发器 function 应该类似于:

CREATE FUNCTION check()
RETURNS TRIGGER
LANGUAGE PLPGSQL
AS $BODY$
BEGIN       
    IF EXISTS ( SELECT 1
                  FROM race AS r
                 INNER JOIN athlete AS a
                    ON r.code_race ~ (a.gender  || '..$')
                 WHERE r.code_race = NEW.codR
                   AND a.code_athlete = NEW.codA
              ) 
    THEN
        RETURN NEW ;
    ELSE
        RAISE EXCEPTION 'It is not possible to add an athlete of a gender that is not compatible with the competition';
        RETURN NULL;
    END IF;
END;
$BODY$

在由触发器调用的 function 中,您可以(必须)使用变量NEW (resp. OLD ) 以便引用要插入或更新的新行 (resp. old row) (resp. only to be updated )在目标表中(在您的情况下为"participation" ),请参阅手册

建议的 function 不需要声明任何变量,因为可以通过建议的sql查询直接执行测试。

建议的 sql 查询:

  • 首先在"race"表中搜索其code_race等于插入/更新值的行partition.codR = NEW.codR
  • 然后在表"athlete"中搜索其code_athlete等于插入/更新值的行partition.codA = NEW.codA
  • 最后使用正则表达式比较从两个表"race""athlete"中选择的行来比较code_racegender值,参见手册

顺便说一句,我没有在表定义中看到serial类型的列 ID 的附加值,特别是因为它们没有用于任何主键或外键。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM