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