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!!! 闲时记录,如有问题请予以指正!!!

相关推荐
OK_boom2 天前
C# Dapper匹配postgresql的jsonb类型
开发语言·postgresql·c#
SelectDB技术团队2 天前
当 PostgreSQL 面临性能瓶颈:80TB 电商业务迁移至 Apache Doris 的实践思考
数据库·postgresql·apache
梦想画家2 天前
告别轮询:基于PostgreSQL CDC构建实时数据管道
数据库·postgresql·kafka·实时湖仓
粗体鱼2 天前
RAG/Agent 记忆混合检索多路召回:RRF 算法与Chunk RRF、Document RRF如何决策TopK
postgresql·milvus·es·rag·rff·mermory
SelectDB2 天前
当 PostgreSQL 面临性能瓶颈:80TB 电商业务迁移至 Apache Doris 的实践思考
postgresql
IvorySQL2 天前
PG 日报|PG20 正式计划移除 refint 模块,官方指引迁移原生外键
数据库·人工智能·postgresql·开源·区块链
2601_960906722 天前
华为MateBook Pro S首发搭载麒麟XE90
华为·postgresql·sqlite·时序数据库·tdengine
丘丘用户思思澪3 天前
混合检索的极简主义:PostgreSQL + pgvector 生产级方案
数据库·postgresql·bm25·vectordb
依晨照旧3 天前
PostgreSQL 常用命令速查:MySQL 用户平滑上手,psql 元命令 + 库表管理 + 运维排查一篇通
后端·postgresql
AAA@峥3 天前
PostgreSQL 入门与实战指南|从基础概念到 CentOS 部署、运维、CRUD 完整教程
运维·postgresql·centos