PostgreSQL - 根据另一个单元格值设置默认单元格值

问题描述 投票:0回答:2

如果我有一列说任何给定值的

column a
,并且我希望另一列
column b
根据
default value
的值有一个
column a

换句话说:
如果

column a = 'peter'
那么
column b default value = 'doctor'
.

postgresql database-design triggers default-value postgresql-9.2
2个回答
75
投票

这是不可能一个简单的

DEFAULT
值,因为手册明确指出

值为任意无变量表达式(子查询和 不允许交叉引用当前表中的其他列)。

您可以改用触发器

CREATE OR REPLACE FUNCTION trg_foo_b_default()
  RETURNS trigger
  LANGUAGE plpgsql AS
$func$
BEGIN
   -- For just a few constant options, CASE does the job:
   NEW.b := CASE NEW.a
               WHEN 'peter'  THEN 'doctor'
               WHEN 'weirdo' THEN 'shrink'
               WHEN 'django' THEN 'undertaker'
            -- ELSE null default
            END;

   /*
   -- For more, or dynamic options, consider a lookup table:
   SELECT INTO NEW.b  t.b
   FROM   def_tbl t
   WHERE  t.a = NEW.a;
   */

   RETURN NEW;
END
$func$;


CREATE TRIGGER b_default
BEFORE INSERT ON foo
FOR EACH ROW
WHEN (NEW.b IS NULL AND NEW.a IS NOT NULL)
EXECUTE FUNCTION trg_foo_b_default();

对于 Postgres 10 或更早版本,请改用

EXECUTE PROCEDURE ...
。参见:

为了使其更有效,请在触发器定义中使用

WHEN
子句(自 Postgres 9.0 起可用)。这样触发函数只有在真正有用的时候才会执行。 (假设如果
b IS NULL
我们可以让
a IS NULL
滑动。)

在 Postgres 12 或更高版本中,

GENERATED
列可能是更好的解决方案。见jian的补充答案。但是请注意,手册中的这些限制:

生成表达式可以引用表中的其他列,但是 不是其他生成的列。使用的任何函数和运算符必须 不可变的。不允许引用其他表。

这个触发器与DEFAULT

有细微的不同,因为b
中的null总是被替换为从
a
派生的值,而
DEFAULT
只是默认值,可以用任何显式输入来否决.

GENERATED
 列不允许输入以开头。


19
投票
在 PostgreSQL 12 或更高版本中,我们可以使用

生成的列
https://www.postgresql.org/docs/12/ddl-generated-columns.html 例子:

create temp table foo ( a text, b text GENERATED ALWAYS AS ( case WHEN a = 'telegram' THEN 'im' WHEN a = 'proton' THEN 'email' WHEN a = 'infinity' THEN 'idea' ELSE 'bad idea' end) stored );
--测试时间。

insert into foo(a) values ('infinity'); insert into foo(a) values ('infinity1');
退货;

a | b -----------+---------- infinity1 | bad idea infinity | idea
当你尝试

insert into foo(b) values ('infinity1')

 yield Errors.

--ERROR: cannot insert into column "b" DETAIL: Column "b" is a generated column.
    
© www.soinside.com 2019 - 2024. All rights reserved.