Postgresql插入触发器来设置值

时间:2013-04-19 10:07:44

标签: postgresql triggers postgresql-9.1

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

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

这可能吗?

2 个答案:

答案 0 :(得分:73)

您需要触发器是正确的,因为设置列的默认值对您不起作用 - 默认值仅适用于null值,并且不会帮助您防止空白值。< / p>

在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()

你已经完成了。

请参阅the above code executing on SQLFIddle,证明其工作正常!


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

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

答案 1 :(得分:9)

有可能,但您最好不要在列上设置默认约束。在创建看起来像这样的表时:

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;

函数的声明是不可变的,但是如果你想索引&#34;列&#34;则需要它。您可以像这样索引此列:

create index on mytable (C1(mytable));