postgres 序列 SEQUENCE

前言

postgres简单使用navicat备份数据库时,若存在自增字段会导致数据备份失败

序列相关查询

获取库中的序列

sql 复制代码
SELECT table_name, column_name, substr(column_default, 10,"length"(column_default)-21) AS serial_sequence
FROM information_schema.columns
WHERE table_schema = 'public'
AND column_default LIKE 'nextval%' 

获取序列信息

sql 复制代码
SELECT * FROM information_schema.sequences

另外一种查询方式

sql 复制代码
-- 查看 r =普通表, i =索引,S =序列,v =视图,m =物化视图, c =复合类型,t = TOAST表,f =外部表 
select * from pg_class where relkind='S';

获取序列值

sql 复制代码
SELECT currval('test_one_id_seq')

上述代码中currval()中输入为序列名称。

此时会有两种结果,如果表没有数据,或者序列为1时,会报错!!!

正常显示

根据表和字段获取序列

sql 复制代码
SELECT pg_get_serial_sequence('test_one', 'id');

pg_get_serial_sequence(表名,字段) 如果是存在序列 返回序列名,否则返回null

存在:

不存在:

序列操作

创建序列

圆规正传,回到我们开头的问题,提示我们关系不存在,那么我们只要创建关系即可

sql 复制代码
--简单创建
CREATE SEQUENCE "public".序列名称;
--自定义创建
CREATE SEQUENCE "public".序列名称 INCREMENT 1 MINVALUE 1 MAX 999999999 STAER 1 CACHE 1;
--参数说明
--INCREMENT 1  代表每次新增序列加1
--MINVALUE 1  代表最小值为 1 NO MINVALUE 代表则不设最小值
--MAXVALUE 9999999 代表最大值为 99999999 NO MAXVALUE 代表不设置最值
--START 1 代表初始值为1
--CACHE 1 设置缓存区

创建完成,如下图

重新导入,导入完成

虽然导入完成了但是存在一个bug,当我们重新插入数据是大概率会遇到id已存在的错误,

我们打开导出的sql查看内容

发现导入数据是id的值是已填的,这样不会触发id的自增效果,所以序列的初始值一直是0的状态 所以为了引起不必要的bug,我们需要把序列更新成id的最大值即可。

修改序列值

下方设置序列值为1000,则下一次插入的值为1001

sql 复制代码
SELECT setval('序列名', 1000);

另外的更新方式

sql 复制代码
ALTER SEQUENCE 序列名 RESTART WITH 1000;

删除

sql 复制代码
--删除 
drop sequence xxx_no_seql;

函数更新序列值

上方提供了单个表更新序列的方法,如果遇到1个表还行哈,但是遇到多个表,假如100个表,我们能一个一个的修改序列的值嘛,经过我历时两年半的学习,使用函数可以完美解决这个问题,下面是我历时年半的成果!

sql 复制代码
CREATE OR REPLACE FUNCTION "public"."reset_all_sequences_max"("p_schema_name" text)
  RETURNS "pg_catalog"."varchar" AS $BODY$
DECLARE
		v_max_value bigint;
		v_seq RECORD;
BEGIN
  -- 获取所有表
    FOR v_seq IN
    SELECT
    substr(column_default, 10,"length"(column_default)-21) AS sequence_name,
    "table_name",
    "column_name"
    FROM information_schema.columns
    WHERE column_default LIKE 'nextval%'
    AND table_schema = p_schema_name
    LOOP
        IF v_seq.sequence_name IS NOT NULL THEN	
            -- 获取表字段的最大值
            EXECUTE 'SELECT MAX(' || quote_ident(v_seq.column_name) || ') FROM ' || quote_ident(p_schema_name) || '.' || quote_ident(v_seq.table_name)
            INTO v_max_value;
                IF v_max_value IS NOT NULL THEN
                    -- 重置序列的值为表字段的最大值
                    EXECUTE 'SELECT setval(''' || v_seq.sequence_name || ''', ' || v_max_value || ')';
                ELSE
            END IF;
        END IF;
    END LOOP;
    RETURN 'All sequences reset successfully for table';

    EXCEPTION
        WHEN OTHERS THEN
            RETURN 'An error occurred: ' || SQLERRM;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100

选择函数

p_schema_name的值传入指定模式即可,本文章使用模式为 pubilc

执行函数

执行完成!

第二种方式,从创建时解决问题,不过这个方法会使原始库的自增id加1

sql 复制代码
SELECT 'CREATE SEQUENCE '||substr(column_default, 10,"length"(column_default)-21)||' INCREMENT 1 START '|| nextval(substr(column_default, 10,"length"(column_default)-21))||';'
FROM information_schema.columns
WHERE table_schema = 'public'
AND column_default LIKE 'nextval%' 

只需要导出结果,然后在迁移前备份即可

nextval() 可以换成 currval() 使用currval方法有序列值为空引起报错风险,可以先currval报错了就用nextval!!! 闲时记录,如有问题请予以指正!!!

相关推荐
特立独行的猫a2 小时前
使用Docker/Docker Compose方式安装部署PostgreSQL指南
docker·postgresql·容器
yinshuilan3 小时前
Postgresql安装配置
数据库·postgresql
好记忆不如烂笔头abc4 小时前
ubuntu20.04桌面允许root用户登录
服务器·数据库·postgresql
zdd567895 小时前
GIN索引原理
运维·算法·postgresql
钱彬 (Qian Bin)20 小时前
项目实践13—全球证件智能识别系统(内网离线部署大模型并调用)
数据库·postgresql·fastapi·ubuntu24.04·离线部署·qwen3大模型
l1t21 小时前
在postgres和duckdb中比较两个数组并只挑选不匹配的元素
数据库·sql·postgresql·数组·duckdb
东东的脑洞1 天前
【面试突击】PostgreSQL vs MySQL 索引架构深度对比:聚簇索引 vs 堆表
mysql·postgresql·面试
nvd111 天前
在 Cloud SQL for PostgreSQL 上启用 pgvector
数据库·postgresql
兴趣互联2 天前
PostgresSQL数据库如何使用navicat创建分区表
数据库·postgresql
l1t2 天前
修改一个触发PostgreSQL 17.2 bug的SQL
sql·postgresql·bug