Postgresql 插入触发器以设置值

Posted

技术标签:

【中文标题】Postgresql 插入触发器以设置值【英文标题】:Postgresql insert trigger to set value 【发布时间】:2013-04-12 16:52:47 【问题描述】:

假设在 Postgresql 中,我有一个表 T,其中一列是 C1

我想在向表T 添加新记录时触发一个函数。该函数应检查新记录中C1 列的值,如果它为空/空,则将其值设置为'X'

这可能吗?

【问题讨论】:

请注意这个值 X 必须从另一个子查询中检索。 【参考方案1】:

您是正确的,您需要一个触发器,因为为列设置默认值对您不起作用 - 默认值仅适用于 null 值,并且不能帮助您防止出现空白值。

在 postgres 中创建触发器有几个步骤:

第 1 步:创建返回类型 trigger 的函数:

CREATE FUNCTION my_trigger_function()
RETURNS trigger AS $$
BEGIN
  IF NEW.C1 IS NULL OR NEW.C1 = '' THEN
    NEW.C1 := 'X';
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql

第 2 步:创建一个触发 before 插入的触发器,它允许您在插入之前更改值,它调用上述函数:

CREATE TRIGGER my_trigger
BEFORE INSERT ON T
FOR EACH ROW
EXECUTE PROCEDURE my_trigger_function()

你已经完成了。

查看the above code executing on SQLFIddle 证明它工作正常!


您在评论中提到值 'X' 是从子查询中检索的。如果是这样,请将相关行更改为:

NEW.C1 := (select some_column from some_table where some_condition);

【讨论】:

感谢您的回答。这正是我想要的。 你为什么不使用$$,而是使用' @StefanFalk 一个可能的原因是像 DbVisualizer 这样的软件在$$ 上存在分隔符问题。在你指出之前,我一直被剥夺使用函数的权利! 如果你不喜欢 IF,你可以使用一个带有 coalesce() 的单行代码,比如:new.c1 := coalesce (new.c1,X);【参考方案2】:

这是可能的,但您最好在列上设置默认约束。创建表时,如下所示:

create table mytable as (
    C1 thetype not null default X
);

这表示如果您向表中添加一行并且未指定 C1 的值,则将使用 X 代替。 not null 不是必需的,但可以防止更新将该列设为空,假设这是您想要的。

编辑:这仅适用于常量 X,从您的 cmets 看来有两种可能的解决方案。

使用触发器看起来像这样:

create function update_row_trigger() returns trigger as $$
begin
    if new.C1 is NULL then
        new.C1 := X;
    end if;
    return new;
end
$$ language plpgsql;

create trigger mytrigger before insert on mytable for each row execute procedure update_row_trigger();

触发器函数中的new 变量很特殊,表示正在插入的行。将触发器指定为before insert 触发器意味着您可以在将行写入表之前对其进行修改。

第二种解决方案是使用 Postgres 以不同寻常的方式定义的计算列:

create or replace function C1(row mytable) returns columntype immutable as $$
begin
    return X; -- where X is an expression using values from `row`
end
$$ language plpgsql;

这将创建一个函数,该函数获取表中的一行并返回一个值,您可以使用 .符号虽然,这意味着你可以这样做:

select
    *,
    t.C1
from
    mytable t;

函数不可变的声明是可选的,但如果你想索引“列”,它是必需的。您可以像这样索引此列:

create index on mytable (C1(mytable));

【讨论】:

谢谢,但在我的情况下,将值设置为默认约束时出现错误。因为这个值 X 是通过子查询获得的,所以它是不允许的。你能告诉我一个解决方法吗? C1 的值是由同一行中的其他值唯一确定的,还是取决于其他因素,例如一天中的时间或其他表中的数据? 是唯一确定的。只需通过(从 Table2 中选择 id,其中 name = 'Unique_Value')来检索它。这个 id 在不同的数据库中可能不同,因此必须始终从子查询中检索它。

以上是关于Postgresql 插入触发器以设置值的主要内容,如果未能解决你的问题,请参考以下文章

表中的递增/递减计数值取决于使用 postgresql 中的触发器插入/删除另一个表的特定列值

PostgreSQL:如何在不延迟插入响应的情况下执行插入触发器?

检查 postgresql 的返回查询中是不是存在值

PDO postgresql 最后插入的 id 返回 'false' 或 -1

PostgreSQL 函数和触发器在 postgresql 中包含更改

无法使用 spring boot 和 postgresql 获取布尔值以进行插入