2017-10-10 6 views
1

Je souhaite mettre une contrainte sur un champ de date de naissance pour l'une de mes tables db. Essentiellement, je veux m'assurer que pat_dob_dt date d'au moins 16 ans (à compter de la date du jour). J'utilise PostgreSQL 8.4.20 et utilisé pour le guidage here:PostgreSQL Trigger/Fonction pour m'assurer que la date est passée

CREATE OR REPLACE FUNCTION patient_dob_in_past() 
RETURNS TRIGGER AS $$ 
BEGIN 
-- check pat_dob_dt is in past -- 
    IF (NEW.pat_dob_dt > current_date - interval '16 years') THEN 
     RAISE EXCEPTION '% must be 16 years in past', NEW.pat_dob_dt 
    END IF; 
    RETURN NEW; 
END; 
$$ language 'plpgsql'; 


CREATE OR REPLACE TRIGGER patient_dob_in_past BEFORE UPDATE OR INSERT 
ON patients FOR EACH ROW EXECUTE PROCEDURE patient_dob_in_past(); 

Malheureusement, je suis rencontré l'erreur suivante

ERROR: syntax error at or near "END" at character 14 
QUERY: SELECT $1 END IF 
CONTEXT: SQL statement in PL/PgSQL function "patient_dob_in_past" near line 4 
LINE 1: SELECT $1 END IF 

Je ne sais pas où je vais mal depuis que je suis les documents pour psql 8.4

EDIT Problème de fonction du point-virgule. Je reçois aussi une erreur pour mon déclencheur

ERROR: syntax error at or near "TRIGGER" at character 19 LINE 1: CREATE OR REPLACE TRIGGER patient_dob_in_past BEFORE UPDATE ...

Répondre

3

essayer:

CREATE OR REPLACE FUNCTION patient_dob_in_past() 
RETURNS TRIGGER AS $$ 
BEGIN 
-- check pat_dob_dt is in past -- 
    IF (NEW.pat_dob_dt > current_date - interval '16 years') THEN 
     RAISE EXCEPTION '% must be 16 years in past', NEW.pat_dob_dt; 
    END IF; 
    RETURN NEW; 
END; 
$$ language 'plpgsql'; 

également https://www.postgresql.org/docs/current/static/sql-createtrigger.html

CREATE OR REPLACE TRIGGER 

échouera car il ne fonctionne pas avec OR REPLACE - utilisez simplement CREATE TRIGGER à la place

aussi pourquoi ne pas cocher contre les entraînements? par exemple:

t=# create table q2(t timestamptz check (t < now() - '16 years'::interval)); 
CREATE TABLE 
t=# insert into q2 select now(); 
ERROR: new row for relation "q2" violates check constraint "q2_t_check" 
DETAIL: Failing row contains (2017-10-10 11:41:01.062535+00). 
t=# insert into q2 select now() - '16 years'::interval; 
ERROR: new row for relation "q2" violates check constraint "q2_t_check" 
DETAIL: Failing row contains (2001-10-10 11:41:13.031769+00). 
t=# insert into q2 select now() - '16 years'::interval -'1 second'::interval; 
INSERT 0 1 

mise à jour

En cas de existantes des valeurs précédentes qui ne correspondent pas à vérifier la contrainte - vous pouvez retarder vérifier avec NOT VALID, par exemple:

t=# create table q2(t timestamptz); 
CREATE TABLE 
t=# insert into q2 select now(); 
INSERT 0 1 
t=# alter table q2 add constraint q2c check (t < (now() - '16 years'::interval)) not valid; 
ALTER TABLE 
t=# insert into q2 select now(); 
ERROR: new row for relation "q2" violates check constraint "q2c" 
DETAIL: Failing row contains (2017-10-10 11:56:02.705578+00). 
+0

erreur me regardait en face. Maintenant, j'ai une erreur avec mon déclencheur. Je n'avais pas considéré une contrainte CHECK. Je suppose que ce serait plus rapide? – moadeep

+0

oui - je suppose qu'il sera à la fois plus rapide et plus net –

+0

Malheureusement, certains de nos anciens enregistrements violent déjà une contrainte. Cela prendrait du temps pour nettoyer la base de données. Probablement plus rapide avec un déclencheur. Une idée de pourquoi mes erreurs de déclenchement? – moadeep

1

Vous avez manqué virgule à la fin de la ligne.

RAISE EXCEPTION '% must be 16 years in past', NEW.pat_dob_dt;