Reputation: 47
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;
Upvotes: 1
Views: 1574
Reputation: 657922
A trigger design is unsafe and expensive trickery that can easily fail under concurrent write load. Don't use a trigger. Use a serial
or IDENTITY
column instead:
Don't use text
(or varchar
) for a numeric
value.
Don't pad leading zeroes. You can format your numbers any way you like for display with to_char()
:
In Postgres 10 or later your table could look like this:
CREATE TABLE s_etpta.tab1 (
number numeric NOT NULL PRIMARY KEY, -- not VARCHAR(40)
id bigint GENERATED ALWAYS AS IDENTITY -- or just int?
);
No trigger.
Seems odd that number
is the PK. Would seem like id
should be. Maybe you do not need the id
column in the table at all?
If you need to get the underlying sequence in sync:
If you cannot fix your table, this trigger function works with the existing one (unreliably under concurrent write load):
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;
Trigger:
CREATE TRIGGER tab1_before_insert
BEFORE INSERT ON schema.tab1
FOR EACH ROW EXECUTE PROCEDURE schema.tab1_number_inc();
The FM
modifier removes leading blanks from to_char()
output:
Upvotes: 1