Postgresql插入触发器以设置值

tyky79it  于 2023-01-25  发布在  PostgreSQL
关注(0)|答案(2)|浏览(156)

假设在Postgresql中,我有一个表T,其中一列是C1
我想在向表T添加新记录时触发一个函数。该函数应检查新记录中列C1的值,如果为null/空,则将其值设置为'X'
这可能吗?

uhry853o

uhry853o1#

您需要触发器是正确的,因为为列设置默认值对您不起作用-默认值只对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 INSERT,它允许您在传入值命中表之前对其进行更改:

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

你就完了。
请参见在SQLFIDdle上执行的上述代码。
您在注解中提到值'X'是从子查询中检索的。如果是这样,请将相关行更改为如下形式:

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

w8f9ii692#

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

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

这意味着如果你向表中添加一行并且不指定C1的值,那么X将被使用。not null不是必需的,但是防止更新将该列置空,假设这是你想要的。
编辑:这只适用于常数X,从你的评论看似乎有两种可能的解决方案。
使用触发器将如下所示:

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;

这将创建一个函数,该函数获取表中的一行并返回一个值,但您可以使用. notation调用它,这意味着您可以执行以下操作:

select
    *,
    t.C1
from
    mytable t;

函数不可变的声明是可选的,但是如果你想索引“column”,就需要这样做。你可以这样索引这个列:

create index on mytable (C1(mytable));

相关问题