以列为前缀的自定义渐进序列(每年)
Custom progressive sequence (per year) with a column as prefix
我需要根据特定列创建自定义序列,添加为前缀。我知道可以自定义序列以及 nextval,但我不确定是否可以使用特定 table.
的列
这是 table 的结构,其中包含基本信息:
create table tab
(
id serial not null
constraint tab_pkey primary key,
year varchar(4) not null,
seq varchar(20) not null
);
create sequence tab_id_seq as integer;
我想按照以下格式自动填充 "seq" 列,就像正常序列一样:
{year}_{sequence}
其中{year}_是前缀,而{sequence}是每年从1重新开始的累进。
DESIRED RESULT
|--------|----------|---------|
| id | year | seq |
|--------|----------|---------|
| 10 | 2019 | 2019_1 |
|--------|----------|---------|
| 11 | 2019 | 2019_2 |
|--------|----------|---------|
| 12 | 2019 | 2019_3 |
|--------|----------|---------|
| 13 | 2019 | 2019_4 |
|--------|----------|---------|
| 14 | 2020 | 2020_1 | <--- sequence restarting
|--------|----------|---------|
| 15 | 2020 | 2020_2 |
|--------|----------|---------|
| 16 | 2020 | 2020_3 |
|--------|----------|---------|
N.B。 id 列与 {sequence} 元素
之间没有直接关系
对于以下测试结构:
create table test
(
id serial primary key
, year_val int
, seq varchar (10)
);
create or replace function fn_test () returns trigger language plpgsql as $$
declare
res_name varchar;
begin
drop table if exists tmp_test;
create temporary table tmp_test as select * from test;
insert into tmp_test values (new.id, new.year_val);
with cte as
(
select *
, year_val::varchar||'_'||(count(*) over (partition by year_val order by id))::varchar as built_res_name
from tmp_test
)
select built_res_name into res_name
from cte
where id = new.id;
new.seq := res_name;
return new;
end;
$$;
CREATE TRIGGER tg_test BEFORE INSERT ON test
FOR EACH ROW EXECUTE FUNCTION fn_test();
insert into test (year_val)
values (2019),(2019),(2019),(2019),(2020),(2020),(2020);
最后我找到了一个解决方案,使用多个序列(每年一个),在输入记录时动态创建。
触发器,在插入之前调用创建序列(如果不存在)并将值分配给 seq 列(如果未分配)的过程。
工作流程
- 记录插入
- 序列创建'tab_ {year} _seq_id'如果不存在
- 如果列 seq 为空,则分配值 nextval (tab_ {year} _seq_id)
- 测试插入和删除以验证列是否以正确的方式填充
TABLE 结构
CREATE TABLE tab (
id serial not null constraint tab_pkey primary key,
year varchar(4) not null,
seq varchar(20)
);
函数
CREATE FUNCTION tab_sequence_trigger_function() RETURNS trigger AS $$
BEGIN
IF NEW.seq IS NULL OR NEW.seq = '''' THEN
EXECUTE ('CREATE SEQUENCE IF NOT EXISTS tab_' || NEW.year || '_id_seq AS INTEGER');
NEW.seq = NEW.year || '_' || nextval('tab_' || NEW.year || '_id_seq');
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
触发
CREATE TRIGGER tab_sequence_trigger
BEFORE INSERT ON tab
FOR EACH ROW
EXECUTE PROCEDURE tab_sequence_trigger_function();
测试
INSERT INTO tab (year) VALUES (2019);
INSERT INTO tab (year) VALUES (2019);
INSERT INTO tab (year) VALUES (2019);
INSERT INTO tab (year) VALUES (2019);
INSERT INTO tab (year) VALUES (2019);
DELETE FROM tab WHERE id=5;
INSERT INTO tab (year) VALUES (2019);
INSERT INTO tab (year) VALUES (2019);
INSERT INTO tab (year) VALUES (2020);
INSERT INTO tab (year) VALUES (2020);
INSERT INTO tab (year) VALUES (2021);
DELETE FROM tab WHERE id=8;
DELETE FROM tab WHERE id=9;
INSERT INTO tab (year) VALUES (2021);
INSERT INTO tab (year) VALUES (2020);
结果
SELECT * FROM tab;
----------------------
| id | year | seq |
----------------------
| 1 | 2019 | 2019_1 |
----------------------
| 2 | 2019 | 2019_2 |
----------------------
| 3 | 2019 | 2019_3 |
----------------------
| 4 | 2019 | 2019_4 |
----------------------
| 6 | 2019 | 2019_6 |
----------------------
| 7 | 2019 | 2019_7 |
----------------------
| 10 | 2021 | 2021_3 |
----------------------
| 11 | 2021 | 2021_4 |
----------------------
| 12 | 2020 | 2020_3 |
----------------------
我需要根据特定列创建自定义序列,添加为前缀。我知道可以自定义序列以及 nextval,但我不确定是否可以使用特定 table.
的列这是 table 的结构,其中包含基本信息:
create table tab
(
id serial not null
constraint tab_pkey primary key,
year varchar(4) not null,
seq varchar(20) not null
);
create sequence tab_id_seq as integer;
我想按照以下格式自动填充 "seq" 列,就像正常序列一样:
{year}_{sequence}
其中{year}_是前缀,而{sequence}是每年从1重新开始的累进。
DESIRED RESULT
|--------|----------|---------|
| id | year | seq |
|--------|----------|---------|
| 10 | 2019 | 2019_1 |
|--------|----------|---------|
| 11 | 2019 | 2019_2 |
|--------|----------|---------|
| 12 | 2019 | 2019_3 |
|--------|----------|---------|
| 13 | 2019 | 2019_4 |
|--------|----------|---------|
| 14 | 2020 | 2020_1 | <--- sequence restarting
|--------|----------|---------|
| 15 | 2020 | 2020_2 |
|--------|----------|---------|
| 16 | 2020 | 2020_3 |
|--------|----------|---------|
N.B。 id 列与 {sequence} 元素
之间没有直接关系对于以下测试结构:
create table test
(
id serial primary key
, year_val int
, seq varchar (10)
);
create or replace function fn_test () returns trigger language plpgsql as $$
declare
res_name varchar;
begin
drop table if exists tmp_test;
create temporary table tmp_test as select * from test;
insert into tmp_test values (new.id, new.year_val);
with cte as
(
select *
, year_val::varchar||'_'||(count(*) over (partition by year_val order by id))::varchar as built_res_name
from tmp_test
)
select built_res_name into res_name
from cte
where id = new.id;
new.seq := res_name;
return new;
end;
$$;
CREATE TRIGGER tg_test BEFORE INSERT ON test
FOR EACH ROW EXECUTE FUNCTION fn_test();
insert into test (year_val)
values (2019),(2019),(2019),(2019),(2020),(2020),(2020);
最后我找到了一个解决方案,使用多个序列(每年一个),在输入记录时动态创建。 触发器,在插入之前调用创建序列(如果不存在)并将值分配给 seq 列(如果未分配)的过程。
工作流程
- 记录插入
- 序列创建'tab_ {year} _seq_id'如果不存在
- 如果列 seq 为空,则分配值 nextval (tab_ {year} _seq_id)
- 测试插入和删除以验证列是否以正确的方式填充
TABLE 结构
CREATE TABLE tab (
id serial not null constraint tab_pkey primary key,
year varchar(4) not null,
seq varchar(20)
);
函数
CREATE FUNCTION tab_sequence_trigger_function() RETURNS trigger AS $$
BEGIN
IF NEW.seq IS NULL OR NEW.seq = '''' THEN
EXECUTE ('CREATE SEQUENCE IF NOT EXISTS tab_' || NEW.year || '_id_seq AS INTEGER');
NEW.seq = NEW.year || '_' || nextval('tab_' || NEW.year || '_id_seq');
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
触发
CREATE TRIGGER tab_sequence_trigger
BEFORE INSERT ON tab
FOR EACH ROW
EXECUTE PROCEDURE tab_sequence_trigger_function();
测试
INSERT INTO tab (year) VALUES (2019);
INSERT INTO tab (year) VALUES (2019);
INSERT INTO tab (year) VALUES (2019);
INSERT INTO tab (year) VALUES (2019);
INSERT INTO tab (year) VALUES (2019);
DELETE FROM tab WHERE id=5;
INSERT INTO tab (year) VALUES (2019);
INSERT INTO tab (year) VALUES (2019);
INSERT INTO tab (year) VALUES (2020);
INSERT INTO tab (year) VALUES (2020);
INSERT INTO tab (year) VALUES (2021);
DELETE FROM tab WHERE id=8;
DELETE FROM tab WHERE id=9;
INSERT INTO tab (year) VALUES (2021);
INSERT INTO tab (year) VALUES (2020);
结果
SELECT * FROM tab;
----------------------
| id | year | seq |
----------------------
| 1 | 2019 | 2019_1 |
----------------------
| 2 | 2019 | 2019_2 |
----------------------
| 3 | 2019 | 2019_3 |
----------------------
| 4 | 2019 | 2019_4 |
----------------------
| 6 | 2019 | 2019_6 |
----------------------
| 7 | 2019 | 2019_7 |
----------------------
| 10 | 2021 | 2021_3 |
----------------------
| 11 | 2021 | 2021_4 |
----------------------
| 12 | 2020 | 2020_3 |
----------------------