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;
答案 0 :(得分:1)
触发器设计是不安全且昂贵的欺骗,很容易在并发写入负载下失败。不要使用触发器。请使用serial
或IDENTITY
列:
请勿将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()
输出中删除前导空白: