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

相关推荐
smallyoung1 天前
数据库乐观锁深度解析:MySQL、PostgreSQL 实战 + Spring Boot 集成指南
数据库·mysql·postgresql
秉承初心16 天前
PostgreSQL 数据性能瓶颈突破实战
数据库·postgresql·oracle
IvorySQL17 天前
PostgreSQL 技术日报 (6月15日)|PG19 性能优化推进,POSETTE 大会倒计时 2 天
数据库·人工智能·postgresql·开源
IvorySQL17 天前
PostgreSQL 技术日报 (6月16日)|Neon 自动化再进一步,逻辑复制冲突日志迎来 v50 更新
数据库·postgresql·自动化
倒流时光三十年17 天前
PostgreSQL 聊一下索引和排序规则
postgresql
睡不醒男孩03082318 天前
PostgreSQL 数据库运维转型:从传统模式到 CLup 平台的 25 个核心 FAQ
运维·数据库·postgresql
JOJO数据科学18 天前
pgAdmin4 Electron 鸿蒙 PC 适配全记录:从白屏到连接 PostgreSQL
postgresql·electron·harmonyos
日取其半万世不竭18 天前
PostgreSQL 跑在 Docker 里怎么备份?恢复成功才算备份成功
数据库·docker·postgresql
倒流时光三十年18 天前
PostgreSQL LEAST 表达式函数详解
数据库·postgresql
Rain50918 天前
2.4. PostgreSQL 数据库连接与实战指南
前端·数据库·人工智能·后端·postgresql·数据分析