自动递增触发器中的第一个值

First values in an auto increment trigger

我在 PostgreSQL 10.3 中使用以下 table:

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

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

该列的类型为 varchar,前缀为零。如果 table 为空,我如何指定我想以 '00000001' 开头?因为当我的 table 中已经有值时,触发器获取最后一个值并为下一个正确的插入递增它,但是当我的 table 为空时,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;

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

  • Auto increment table column

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

不要填充前导零。您可以使用 displayto_char():

以任何您喜欢的方式格式化您的数字
  • How to auto increment id with a character

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

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 应该是。也许您根本不需要 table 中的 id?

  • Gap-less sequence where multiple transactions with multiple tables are involved

如果需要同步底层序列:

  • How to reset postgres' primary key sequence when it falls out of sync?
  • Postgres manually alter sequence

如果您无法修复您的 table,此触发器功能可与现有的一起使用(在并发写入负载下不可靠):

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() 输出中删除前导空格:

  • Remove blank-padding from to_char() output