如何解决在 Postgresql 中创建生成列时出错
CREATE TABLE Person (
id serial primary key,accNum text UNIQUE GENERATED ALWAYS AS (
concat(right(cast(extract year from current_date) as text),2),cast(id as text)) STORED
);
错误:生成表达式不是一成不变的
目标是使用 YYid 填充 accNum 字段,其中 YY 是添加人员的年份的最后两个字母。
我也试过'||'运营商,但没有成功。
解决方法
正如@ScottNeville 正确提到的:
CURRENT_DATE
不是一成不变的。所以它不能用于 GENERATED ALWAYS AS
表达式。
但是,您仍然可以使用触发器来实现此目的:
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();
正如评论中正确提到的@a_horse_with_no_name:您可以将表达式简化为:
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
);
,
我不确定如何解决这个问题(可能是一个触发器),但是 current_date 是一个稳定的函数而不是一个不可变的函数。对于生成的 ID,我相信所有函数调用都必须是不可变的。您可以在此处阅读更多信息https://www.postgresql.org/docs/current/xfunc-volatility.html
我不认为任何获取日期的函数都是不可变的,因为 Postgres 将其定义为“一个 IMMUTABLE 函数不能修改数据库,并且在给定相同参数的情况下保证永远返回相同的结果。”对于返回当前日期的任何内容都不是这样。
我认为最好的办法是使用触发器来执行此操作,以便在插入时设置值。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。