First values in an auto increment trigger

时间:2018-07-24 10:17:08

标签: postgresql triggers auto-increment

I am working with the following table in PostgreSQL 10.3:

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

I need to increment the column id by 1 with every insert. I can't alter the table because I'm not the owner so I have no other choice than to increment a varchar column.

The column is type varchar prefixed with zeros. How can I specify that I want to start with '00000001' if the table is empty? Because when I already have values in my table the trigger gets the last value and increment it for the next insert which is correct, but when my table is empty the id column stays empty since the trigger has no value to increment.

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;

1 个答案:

答案 0 :(得分: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()输出中删除前导空白: