假设在Postgresql中,我有一个表T
,其中一列是C1
。
我想在新记录添加到表T
时触发一个函数。该函数应检查新记录中列C1
的值,如果为空/空,则将其值设置为'X'
。
这可能吗?
答案 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));