61

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

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

这可能吗?

4

2 回答 2

100

您需要触发器是正确的,因为为该列设置默认值对您不起作用 - 默认值仅适用于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 步:创建一个在插入之前触发的触发器,它允许您在插入之前更改值,它调用上述函数:

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);
于 2013-04-19T13:15:02.903 回答
10

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

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;

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

select
    *,
    t.C1
from
    mytable t;

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

create index on mytable (C1(mytable));
于 2013-04-19T10:16:54.397 回答