在Postgresql中创建生成的列时出错

在Postgresql中创建生成的列时出错,postgresql,concatenation,string-concatenation,Postgresql,Concatenation,String Concatenation,错误:生成表达式不是不可变的 目标是用YYid填充accNum字段,其中YY是添加人员时一年中的最后两个字母 我还尝试了“| |”运算符,但没有成功。我不确定如何解决这个问题(可能是触发器),但当前的|日期是一个稳定的函数,而不是一个不变的函数。对于生成的ID,我认为所有函数调用都必须是不可变的。你可以在这里读更多 我不认为任何获取日期的函数都是不可变的,因为Postgres将其定义为“不可变的函数不能修改数据库,并且保证在给定相同参数的情况下永远返回相同的结果。”这对于任何返回当前日期的函数都

错误:生成表达式不是不可变的

目标是用YYid填充accNum字段,其中YY是添加人员时一年中的最后两个字母


我还尝试了“| |”运算符,但没有成功。

我不确定如何解决这个问题(可能是触发器),但当前的|日期是一个稳定的函数,而不是一个不变的函数。对于生成的ID,我认为所有函数调用都必须是不可变的。你可以在这里读更多

我不认为任何获取日期的函数都是不可变的,因为Postgres将其定义为“不可变的函数不能修改数据库,并且保证在给定相同参数的情况下永远返回相同的结果。”这对于任何返回当前日期的函数都不是真的


我认为你最好的办法是用触发器来完成这项工作,所以插入它来设置值。

正如@ScottNeville正确提到的:

当前_日期
不是不变的。因此,它不能用于始终作为表达式生成的

但是,您可以使用触发器实现这一点:

正如注释中正确提到的@a_horse_和_no_名称:您可以将表达式简化为:

CREATE FUNCTION accnum_trigger_function() 
   RETURNS TRIGGER 
   LANGUAGE PLPGSQL
AS $$
BEGIN
   NEW.accNum := right(extract(year from current_date)::text, 2) || NEW.id::text;
   
   RETURN NEW;
END
$$;

CREATE TRIGGER tr_accnum
  BEFORE INSERT
  ON person
  FOR EACH ROW
  EXECUTE PROCEDURE accnum_trigger_function();

由于您不希望更新列,因此当行发生更改时,您可以定义自己的函数来生成数字:

NEW.accNum := to_char(current_date, 'YY') || NEW.id;

或者更简单一点:
到字符(当前日期,'YY')
这很难看。触发器会更好。@Laurenz Albe Yh但对于生成的列,为列插入值很容易引起错误。@BihTracy我不明白。但我想这没关系,如果它能满足你的要求。
NEW.accNum := to_char(current_date, 'YY') || NEW.id;
create function generate_acc_num(id int)
returns text
as
$$
  select to_char(current_date, 'YY')||id::text;
$$
language sql
immutable; --<< this is lying to Postgres!
CREATE TABLE Person 
(
  id  integer generated always as identity primary key,
  acc_num  text UNIQUE GENERATED ALWAYS AS (generate_acc_num(id)) STORED
);