2017-08-05 70 views
2

我正在制作一个数据库,需要为学校系统存储数据,对于某些活动,未成年人需要许可证。 我有这个触发器,检查如果一个参与者是未成年人,那么他需要一个许可证。触发器行为奇怪

CREATE OR REPLACE FUNCTION absent_permit() 
RETURNS trigger AS $body$ 
BEGIN 
    RAISE NOTICE 'ENTERS TRIGGER'; 
    RAISE NOTICE 'AGE NEW PARTICIPANT = %', age_from_participant(NEW.id_part); 
    IF (age_from_participant(NEW.id_part) < 18) AND (NEW.permit IS NULL) THEN 
      RAISE NOTICE 'ENTERS IF'; 
      RAISE NOTICE 'PARTICIPANT UNDER 18 NEED A PERMIT'; 
      RAISE EXCEPTION 'MINOR WITHOUT PERMIT' USING HINT = 'PERMIT MUST BE != NULL'; 
      RETURN NULL; 
    END IF; 
    RAISE NOTICE 'EXIT TRIGGER'; 
    RETURN NEW; 
END 
$body$ 
LANGUAGE plpgsql; 


CREATE TRIGGER check_permit BEFORE INSERT ON participant 
FOR EACH ROW EXECUTE PROCEDURE absent_permit(); 

事实是:我第一次尝试插入一个小未经允许它不会因重复主键工作,反正插入,我第二次尝试给我一个错误相反,触发器工作并引发第一次应该提出的异常。函数age_from_participant确实以正确的方式工作,这不是问题。

有人可以告诉我我做错了什么吗?谢谢

编辑:添加表的人,插入

CREATE TABLE people (
    fiscal_code varchar(16) PRIMARY KEY, 
    name  varchar(20) NOT NULL, 
     surname   varchar(20) NOT NULL, 
     phone  numeric(10, 0) NOT NULL, 
     sex    char(1)  NOT NULL CHECK(sex IN ('M','F')), 
     email  varchar(50) NOT NULL, 
    d_birth  date   NOT NULL 
); 

CREATE TABLE participant (
    id_part   varchar(10) PRIMARY KEY, 
    fiscal_code  varchar(16) NOT NULL REFERENCES people(fiscal_code), 
     documents_code  varchar(1000) NOT NULL, 
     section   varchar(2) NOT NULL, 
     grade   varchar(2) NOT NULL, 
     permit   varchar(500), 
     school_code  varchar(10) NOT NULL REFERENCES schools(school_code) 
); 

CREATE OR REPLACE FUNCTION age_from_participant(varchar) 
RETURNS integer AS $$ 
DECLARE 
    alias_id_part ALIAS FOR $1; 
    precise_age interval; 
BEGIN 
    SELECT AGE(CURRENT_DATE, d_birth) INTO precise_age FROM participant 
     JOIN PEOPLE USING(fiscal_code) 
     WHERE PARTICIPANT.ID_PART = alias_id_part; 
    RETURN date_part('year', precise_age)::INT; 
END $$ 
LANGUAGE plpgsql; 


INSERT INTO people VALUES ('RSSMRC', 'MARCO', 'ROSSI', 3490101123, 'M', '[email protected]', '2000-07-18'); 

INSERT INTO participant VALUES ('PART000001', 'RSSMRC','MR001','A','4',null, 'GEPC01000P'); 

的参与者,例如随着最后插入在第一时间将其插入它的权利,控制台提供:

NOTICE: ENTERS TRIGGER 
NOTICE: AGE NEW PARTICIPANT = 
NOTICE: EXIT TRIGGER 
INSERT 0 1 
Query returned successfully. 

第二次,给出:

ERROR: MINOR WITHOUT PERMIT 
HINT: PERMIT MUST BE != NULL 
CONTEXT: PL/pgSQL function absent_permit() line 8 at RAISE 
********** Error ********** 

ERROR: MINOR WITHOUT PERMIT 
SQL state: P0001 
Hint: PERMIT MUST BE != NULL 
Context: PL/pgSQL function absent_permit() line 8 at RAISE 

EDIT_2: 我解决了将鳕鱼触发器函数中的age_from_partecipant。还是不知道到底是什么没有工作,但这里是工作代码:

CREATE OR REPLACE FUNCTION absent_permit() 
RETURNS trigger AS $body$ 
DECLARE 
    age interval; 
BEGIN 
SELECT AGE(CURRENT_DATE, D_birth) INTO age FROM participant JOIN people USING(fiscal_code) WHERE NEW.fiscal_code = people.fiscal_code; 

    RAISE NOTICE 'ENTERS TRIGGER'; 
    RAISE NOTICE 'AGE NEW PARTICIPANT = %', date_part('year', age)::INT; 
    IF (date_part('year', age)::INT < 18) AND (NEW.permit IS NULL) THEN 
      RAISE NOTICE 'ENTERS IF'; 
      RAISE NOTICE 'PARTICIPANT UNDER 18 NEED A PERMIT'; 
      RAISE EXCEPTION 'MINOR WITHOUT PERMIT' USING HINT = 'PERMIT MUST BE != NULL'; 
      RETURN NULL; 
    END IF; 
    RAISE NOTICE 'EXIT TRIGGER'; 
    RETURN NEW; 
END 
$body$ 
LANGUAGE plpgsql; 


CREATE TRIGGER check_permit BEFORE INSERT ON participant 
FOR EACH ROW EXECUTE PROCEDURE absent_permit(); 
+3

你应该用检查约束来做到这一点,而不是触发器。 –

+0

我尝试过,但无法让它工作,所以我试着用触发器 – Trysme

+0

你可以发布'età_from_participant'的定义吗?你能举一个实际显示行为的最小例子吗? (CREATE table ... CREATE function CREATE trigger ... INSERT INTO参与者...)? – joanolo

回答

0

我不认为età_from_participant()可以找到participant参与者 - 因为交易尚未完成。也就是说,您在插入触发器之前有一个。该行不在表格中。

我的建议是将该逻辑直接移入触发器。或者,也可以创建età_from_person()并将财务代码传递到该函数中。

+0

解决还要感谢turo和joanolo的评论,在帖子末尾添加了工作代码。非常感谢大家 – Trysme