2017-08-05 142 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