自动递增触发器中的第一个值
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;
触发器设计是不安全且昂贵的技巧,很容易在并发写入负载下失败。不要使用触发器。请改用 serial
或 IDENTITY
列:
- Auto increment table column
不要使用 text
(或 varchar
)作为 numeric
值。
不要填充前导零。您可以使用 display 和 to_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
我在 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;
触发器设计是不安全且昂贵的技巧,很容易在并发写入负载下失败。不要使用触发器。请改用 serial
或 IDENTITY
列:
- Auto increment table column
不要使用 text
(或 varchar
)作为 numeric
值。
不要填充前导零。您可以使用 display 和 to_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