PostgreSQL Trigger/Function 以确保日期是过去的
PostgreSQL Trigger/Function to ensure date is in past
我想对我的一个数据库表的出生日期字段施加约束。本质上我想确保 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 END IF
CONTEXT: SQL statement in PL/PgSQL function "patient_dob_in_past" near line 4
LINE 1: SELECT END IF
不确定我哪里出错了,因为我正在关注 8.4 的 psql 文档
编辑
分号修复了函数问题。我的触发器也出现错误
ERROR: syntax error at or near "TRIGGER" at character 19
LINE 1: CREATE OR REPLACE TRIGGER patient_dob_in_past BEFORE UPDATE ...
尝试:
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).
你错过了行尾的分号。
RAISE EXCEPTION '% must be 16 years in past', NEW.pat_dob_dt;
我想对我的一个数据库表的出生日期字段施加约束。本质上我想确保 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 END IF
CONTEXT: SQL statement in PL/PgSQL function "patient_dob_in_past" near line 4
LINE 1: SELECT END IF
不确定我哪里出错了,因为我正在关注 8.4 的 psql 文档
编辑 分号修复了函数问题。我的触发器也出现错误
ERROR: syntax error at or near "TRIGGER" at character 19
LINE 1: CREATE OR REPLACE TRIGGER patient_dob_in_past BEFORE UPDATE ...
尝试:
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).
你错过了行尾的分号。
RAISE EXCEPTION '% must be 16 years in past', NEW.pat_dob_dt;