【问题标题】:First values in an auto increment trigger自动增量触发器中的第一个值
【发布时间】:2018-12-31 22:15:33
【问题描述】:

我正在使用 PostgreSQL 10.3 中的下表:

CREATE TABLE s_etpta.tab1 (
  Number VARCHAR(40) NOT NULL,
  id VARCHAR(8),
  CONSTRAINT i_tab1 PRIMARY KEY(Number)
) 

我需要在每次插入时将列 id 增加 1。我不能更改表,因为我不是所有者,所以我别无选择,只能增加 varchar 列。

该列的类型为varchar,前缀为0。如果表为空,如何指定要以“00000001”开头?因为当我的表中已经有值时,触发器会获取最后一个值并为下一个正确的插入增加它,但是当我的表为空时,id 列保持为空,因为触发器没有要增加的值。

CREATE OR REPLACE FUNCTION schema."Num" (
)
RETURNS trigger AS
$body$
DECLARE    
BEGIN

NEW.id := lpad(CAST(CAST(max (id) AS INTEGER)+1 as varchar),8, '0') from 
schema.tab1;

return NEW;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
RETURNS NULL ON NULL INPUT
SECURITY INVOKER
COST 100;

【问题讨论】:

  • 使用COALESCE,但实际上您应该使用序列,因为这对于并发事务是不安全的。
  • 请记住始终公开您的 Postgres 版本。
  • 不幸的是,我不能更改这些表,因为我不是所有者,所以除了增加一个 varchar 列之外我别无选择。我希望在我的应用中插入时更新该列。
  • 我尝试使用序列 (New.id:=nextval('MySequence')) (但我的序列出现错误“关系不存在”。我正在使用 Sql Manager PostgreSQL 5.9.3
  • 您的客户端(Sql Manager)的版本与此几乎无关。您的 Postgres 版本很重要:SELECT version();

标签: postgresql triggers auto-increment


【解决方案1】:

触发器设计是不安全且昂贵的诡计,在并发写入负载下很容易失败。不要使用触发器。请改用serialIDENTITY 列:

不要将text(或varchar)用作numeric 值。

不要填充前导零。您可以使用to_char()显示 以任何您喜欢的方式格式化您的数字:

在 Postgres 10 或更高版本中,您的表格可能如下所示:

CREATE TABLE s_etpta.tab1 (
  number numeric NOT NULL PRIMARY KEY,         -- not VARCHAR(40)
  id     bigint GENERATED ALWAYS AS IDENTITY   -- or just int?
);

没有触发器。

number 是 PK 似乎很奇怪。看起来应该是id。也许您根本不需要表中的id

如果您需要同步底层序列:


如果你不能修复你的表,这个触发器函数可以与现有的表一起工作(在并发写入负载下不可靠):

CREATE OR REPLACE FUNCTION schema.tab1_number_inc()
  RETURNS trigger AS
$func$
DECLARE    
BEGIN
   SELECT to_char(COALESCE(max(id)::int + 1, 0), 'FM00000000')
   FROM   schema.tab1
   INTO   NEW.id;

   RETURN NEW;
END
$func$  LANGUAGE plpgsql;

触发器:

CREATE TRIGGER tab1_before_insert
BEFORE INSERT ON schema.tab1
FOR EACH ROW EXECUTE PROCEDURE schema.tab1_number_inc();

FM 修饰符从to_char() 输出中删除前导空格:

【讨论】:

  • 感谢您的解释。但是就像我在之前的评论中所说的那样,我不是所有者,我不能更改桌子(这会更安全),所以我别无选择thant 将 varchar 转换为 int ,反之亦然以将其插入我的表中。我正在寻找一种方法来强制插入为我的 id 列具有特定值。
  • @user3365621:我添加了一个“工作”功能——当你被你不幸的桌子设计困住时。
  • @user3365621:我添加了COALESCE 来处理空表的情况——你最初的问题。 :)
  • 完美。谢谢。
猜你喜欢
  • 2020-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多