PL/pgSQL 重启生成序列

Posted

技术标签:

【中文标题】PL/pgSQL 重启生成序列【英文标题】:PL/pgSQL restart generated sequence 【发布时间】:2021-08-29 14:27:15 【问题描述】:

我有一个在 Spring Boot 应用程序启动时使用的初始化脚本,如果表不存在,我会创建它。然后我从表中删除所有数据并在插入时执行一堆。

create table if not exists employee (
    id serial primary key,
    name varchar(255)
);

delete from employee;

-- inserts

每次执行脚本时,序列仍会继续,因此新行不会从一开始。我也必须重置这样的序列,但是,它是生成的,除非我调用这个脚本,否则我不知道它的名字:

select pg_get_serial_sequence('employee', 'id');
-- returns public.employee_id_seq

我尝试将它们组合在一起并根据此功能的输出重置序列,但没有运气。如何在不知道其名称的情况下重置生成的序列?到目前为止,我的尝试无法从变量中解析 seq 序列:

do $$
    declare
        seq varchar(255);
    begin
        select pg_get_serial_sequence('employee', 'employee_id') into seq;
        alter sequence seq restart with 1;
end; $$;

【问题讨论】:

【参考方案1】:

最简单的解决方案是使用truncate table . . . restart identity 而不是delete

truncate table employee restart identity;

Here 是一个 dbfiddle。

Truncate table 也因其他原因而被推荐。例如,它立即回收表使用的空间。而且速度要快得多。一个区别是delete 触发器未被调用(尽管您的表没有任何触发器)。

【讨论】:

【参考方案2】:

将id序列重置为任何数字基本上是一个坏主意,因此您必须非常小心地使用以下内容。

尤其是当您有 id firld 的外键时

你要找的卡是

ALTER SEQUENCE <table_name>_<id_column>_seq RESTART WITH 1
create table if not exists employee (
    id serial primary key,
    name varchar(255)
);
INSERT INTO employee (name) VALUES ('a'),('B'),('C')
3 行受影响
delete from employee;
3 行受影响
ALTER SEQUENCE employee_id_seq RESTART WITH 1
INSERT INTO employee (name) VALUES  ('a')
1 行受影响
SELECT * FROM employee
编号 |姓名 -: | :--- 1 |一种

db小提琴here

【讨论】:

感谢您的快速回答。我知道重置序列的后果。 PostgreSQL 是否保证生成的模式总是&lt;table_name&gt;_&lt;id_column&gt;_seq 是的,模式始终与我的回答中描述的相同

以上是关于PL/pgSQL 重启生成序列的主要内容,如果未能解决你的问题,请参考以下文章

在 PL/pgSQL 中插入后获取默认序列值

使用 PostgreSQL PL/pgSQL 在 For 循环中添加月份

重构 PL/pgSQL 函数以返回各种 SELECT 查询的输出

PL/pgSQL 中的 EXECUTE...USING 中忽略了 USING 部分

PL/pgSQL 中的“格式错误的数组文字”错误

PL/pgSQL 语法错误