PostgreSQL触发器/函数确保日期过去

时间:2017-10-10 11:32:08

标签: sql postgresql plpgsql database-trigger

我想对我的一个数据库表的出生日期字段进行约束。基本上我想确保pat_dob_dt至少在16年前(从当前日期开始)。我正在使用PostgreSQL 8.4.20并使用here作为指导:

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();

不幸的是我遇到了以下错误

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

因为我正在关注8.4

的psql文档,因此不确定我的错误

EDIT 分号修复了功能问题。我的触发器也出现错误

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

2 个答案:

答案 0 :(得分:3)

尝试:

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';

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

CREATE OR REPLACE TRIGGER 

将失败,因为它不能与OR REPLACE一起使用 - 只使用CREATE TRIGGER而不是

为什么不CHECK约束?例如:

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

<强>更新

如果现有的先前值与检查约束不匹配 - 您可以延迟检查NOT VALID,例如:

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).

答案 1 :(得分:1)

你在行尾错过了分号。

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