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



如果我有任何给定值的column a列,并且我希望另一列column b根据column a的值具有default value

换句话说:
if column a = 'peter' then column b default value = 'doctor' .

这是不可能的使用一个简单的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列可能是更好的解决方案。见简补充的回答。但是,请注意手册中的这些限制:

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

此触发器DEFAULT略有不同,因为b中的null总是被替换为从a派生的值,而DEFAULT只是默认值,可以通过任何显式输入来推翻。
GENERATED列不允许输入以。

开头。

在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.

最新更新