使默认值引用另一个 table 的 PostgreSQL 触发器
PostgreSQL trigger to make default value refer to another table
PostgreSQL 默认值不能包含变量或引用 table 或不同的 table.
中的任何其他列
但是,是否可以使用触发器来创建一个 "Default value" 将按以下方式运行。首先,让我用两个例子来说明 tables:
create table projects
(
id serial primary key,
created_at timestamp with time zone default now()
);
create table last_updated
(
project_id integer primary key references projects,
updated_at timestamp with time zone default ...
);
在第二个 table (last_updated
) 中,我希望默认值类似于 default projects(created_at)
。 IE。如果未为 updated_at
指定日期,请查看项目 table 中引用的 project_id,找到 created_at 日期,并将 updated_at 设置为此日期。但是,你不能按照我问题的第一段来写。
那么您如何编写提供此功能的触发器?
正确答案取决于您未指定的内容。通常,人们会对 projects
table 进行更新,然后在 last_updated
table 中使用 table 上的 AFTER UPDATE
触发器审核 table projects
:
CREATE FUNCTION audit_project_update () RETURNS trigger AS $$
BEGIN
INSERT INTO last_updated VALUES
(NEW.id, -- NEW refers to the updated record in the projects table
now() -- this would be the logical value, but can use NEW.created_at
-- other columns, possibly log session_user
);
RETURN NEW;
END; $$ LANGUAGE plpgsql;
CREATE TRIGGER tr_projects_update
AFTER UPDATE ON projects
FOR EACH ROW EXECUTE PROCEDURE audit_project_update();
请注意,在这种方法中,永远不会出现在 table last_updated
上创建 INSERT
而未指定 updated_at
值的情况,假设您会不是 GRANT INSERT
table last_updated
上的任何角色,因为触发函数总是指定 now()
。在 table 定义中,您不必再指定默认值:触发器会为您提供所需的自动化行为。
您提出的问题 - 并在下面的评论中得到确认 - 也将使用触发器,但随后在 last_updated
table:
CREATE FUNCTION project_last_updated () RETURNS trigger AS $$
BEGIN
IF (NEW.updated_at IS NULL) THEN
SELECT created_at INTO NEW.updated_at
FROM projects
WHERE id = NEW.project_id;
END IF;
RETURN NEW;
END; $$ LANGUAGE plpgsql;
CREATE TRIGGER tr_projects_update
BEFORE INSERT ON last_updated
FOR EACH ROW EXECUTE PROCEDURE project_last_updated();
此规范回避了一个问题,即为什么您不简单地将列 updated_at
添加到 projects
table。由于 project_id
列是 last_update
table 中的 PK,因此每个项目只能存储一个最后更新日期。
PostgreSQL 默认值不能包含变量或引用 table 或不同的 table.
中的任何其他列但是,是否可以使用触发器来创建一个 "Default value" 将按以下方式运行。首先,让我用两个例子来说明 tables:
create table projects
(
id serial primary key,
created_at timestamp with time zone default now()
);
create table last_updated
(
project_id integer primary key references projects,
updated_at timestamp with time zone default ...
);
在第二个 table (last_updated
) 中,我希望默认值类似于 default projects(created_at)
。 IE。如果未为 updated_at
指定日期,请查看项目 table 中引用的 project_id,找到 created_at 日期,并将 updated_at 设置为此日期。但是,你不能按照我问题的第一段来写。
那么您如何编写提供此功能的触发器?
正确答案取决于您未指定的内容。通常,人们会对 projects
table 进行更新,然后在 last_updated
table 中使用 table 上的 AFTER UPDATE
触发器审核 table projects
:
CREATE FUNCTION audit_project_update () RETURNS trigger AS $$
BEGIN
INSERT INTO last_updated VALUES
(NEW.id, -- NEW refers to the updated record in the projects table
now() -- this would be the logical value, but can use NEW.created_at
-- other columns, possibly log session_user
);
RETURN NEW;
END; $$ LANGUAGE plpgsql;
CREATE TRIGGER tr_projects_update
AFTER UPDATE ON projects
FOR EACH ROW EXECUTE PROCEDURE audit_project_update();
请注意,在这种方法中,永远不会出现在 table last_updated
上创建 INSERT
而未指定 updated_at
值的情况,假设您会不是 GRANT INSERT
table last_updated
上的任何角色,因为触发函数总是指定 now()
。在 table 定义中,您不必再指定默认值:触发器会为您提供所需的自动化行为。
您提出的问题 - 并在下面的评论中得到确认 - 也将使用触发器,但随后在 last_updated
table:
CREATE FUNCTION project_last_updated () RETURNS trigger AS $$
BEGIN
IF (NEW.updated_at IS NULL) THEN
SELECT created_at INTO NEW.updated_at
FROM projects
WHERE id = NEW.project_id;
END IF;
RETURN NEW;
END; $$ LANGUAGE plpgsql;
CREATE TRIGGER tr_projects_update
BEFORE INSERT ON last_updated
FOR EACH ROW EXECUTE PROCEDURE project_last_updated();
此规范回避了一个问题,即为什么您不简单地将列 updated_at
添加到 projects
table。由于 project_id
列是 last_update
table 中的 PK,因此每个项目只能存储一个最后更新日期。