序列(sequence)是 PostgreSQL 中的一种对象,用于生成自动递增的唯一标识符。通常,序列会与表的自增主键一起使用,以确保每个新插入的行都有一个唯一的标识符。在某些情况下,可能需要更新序列的值:

从另一个数据库中导入数据,自增列的值也从原来的数据中导入。导入的过程中,目标数据库的序列不会得到更新,这样如果执行数据库的插入操作,会出现主键冲突的问题。(感觉非常莫名其妙)

如果数据不是很多的情况下,可以通过多次插入,每次都忽略错误,最后序列自增上来了,就可以插入成功了。

本文将介绍如何查询和更新 PostgreSQL 表的序列,并写一个存储过程进行批量操作。

序列与自增主键

在 PostgreSQL 中,序列是由一个名称、一个当前值和递增步长组成的对象。表的自增主键通常依赖于序列来生成唯一的标识符。以下 SQL 语句创建了一个名为 my_table 的表,该表包含一个自增主键列 id

CREATE TABLE my_table (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);

SERIAL 类型实际上是一个整数类型,并且在表中创建一个名为 my_table_id_seq 的序列对象。每当您向表中插入一行时,PostgreSQL 将自动递增序列并将其值分配给 id 列。

查询表的序列

要查询表的序列,在 PostgreSQL 中,您可以执行以下 SQL 语句:

SELECT pg_get_serial_sequence('my_table', 'id');

这将返回与 my_table 表的 id 列对应的序列名称。请注意,参数的第一个要为标准名称,第二列则需要是纯字符串,对于有大小写的情况,要注意引号的用法:

SELECT pg_get_serial_sequence('"AData"', 'Id');

更新表的序列

要更新表的序列,可以使用setval方法。以下 SQL 语句将将序列 my_table_id_seq 的下一个值设置为 100:

SELECT setval('my_table_id_seq', 100);

我们可以统计当前的最大值,直接将最大值+1赋值给它,对于大小写的情况,也得注意:

SELECT SETVAL('"AData_Id_seq"', (SELECT MAX("Id") + 1 FROM "AData"));

自动化操作

一个个调用还是非常麻烦,我创建了一个函数,可以用来批量更新指定schema内的序列,并利用临时表返回更新的表格与更新的结果。

CREATE OR REPLACE FUNCTION "public"."update_sequence_values"()
RETURNS TABLE("var_table_schema" text, "var_table_name" text, "old_max_id" int4, "new_max_id" int4) AS $$
DECLARE
table_rec RECORD;
max_id INTEGER;
old_max_id_val INTEGER;
BEGIN
-- 创建临时表以保存更新的序列值
DROP TABLE IF EXISTS temp_sequence_updates;
CREATE TEMP TABLE temp_sequence_updates (
var_table_schema TEXT,
var_table_name TEXT,
old_max_id INTEGER,
new_max_id INTEGER
); -- 遍历指定模式下所有包含自增主键的表
FOR table_rec IN (SELECT DISTINCT(table_schema), table_name, is_identity, column_name FROM information_schema.columns WHERE is_identity= 'YES' AND table_schema = 'public') LOOP
EXECUTE format('SELECT MAX(%I) FROM %I.%I;', table_rec.column_name, table_rec.table_schema, table_rec.table_name) INTO max_id; -- 更新序列
IF max_id IS NOT NULL THEN
EXECUTE format('SELECT setval(pg_get_serial_sequence(''%I'', ''%s''), %s, false);', table_rec.table_name, replace(table_rec.column_name, '"','') , max_id + 1); -- 记录更新操作的日志信息
INSERT INTO temp_sequence_updates (var_table_schema, var_table_name, old_max_id, new_max_id) VALUES (table_rec.table_schema, table_rec.table_name , max_id, max_id + 1);
END IF;
END LOOP; -- 返回更新操作的日志信息
RETURN QUERY SELECT * FROM temp_sequence_updates;
END;
$$ LANGUAGE plpgsql; SELECT * FROM update_sequence_values();

注意:

  1. 格式化字符%s%I有不同,在 PostgreSQL 中,%I 是格式化字符串中的一个占位符,用于在 SQL 查询中引用标识符(如列名、表名等)。它类似于 %s 占位符,但是会将参数中的标识符转换为带有双引号的字符串,以防止 SQL 注入攻击。对于setval参数,需要灵活选择使用%s与%I
  2. 函数使用is_identity()来判断是否为自增的列。

注意事项

在更新表的序列时,请注意以下几点:

  • 序列是全局对象,因此在更新前,请确保没有其他用户当前正在使用该序列。
  • 一定多检查,不要更新错误的序列。
  • 操作之前先备份数据。

批量更新Postgresql的序列的更多相关文章

  1. SQL 将2张不相关的表拼接成2列,批量更新至另一张表

    update SO_Master set LotteryNo=t2.LotteryNo,UpdateTime=GETDATE() --select sm.LotteryNo,sm.SysNo,t2.L ...

  2. spring data jpa开启批量插入、批量更新

    spring data jpa开启批量插入.批量更新 原文链接:https://www.cnblogs.com/blog5277/p/10661096.html 原文作者:博客园--曲高终和寡 *** ...

  3. 转://批量更新sequence的存储

    前言: ORACLE的序列(SEQUENCE)A SCHEMA OBJECT THAT GENERATES A SERIAL LIST OF UNIQUE NUMBERS FOR TABLE COLU ...

  4. FreeSql (十四)批量更新数据

    FreeSql支持丰富的更新数据方法,支持单条或批量更新,在特定的数据库执行还可以返回更新后的记录值. var connstr = "Data Source=127.0.0.1;Port=3 ...

  5. update批量更新某一列成其它列对应的值【原】

    update批量更新某一列成其它列对应的值 postgresql 标准sql语句 update AA set name = BB.name , AA.sex = BB.sex from BB wher ...

  6. SQL批量更新 关系表更新

    很多人在做数据的批量更新时..如果更新的内容是从其他表查出来的..很容易这么写.. UPDATE TABLE1 SET COLUMN1=(SELECT SUM(SOMETHING) FROM TABL ...

  7. [PDO绑定参数]使用PHP的PDO扩展进行批量更新操作

    最近有一个批量更新数据库表中某几个字段的需求,在做这个需求的时候,使用了PDO做参数绑定,其中遇到了一个坑. 方案选择 笔者已知的做批量更新有以下几种方案: 1.逐条更新 这种是最简单的方案,但无疑也 ...

  8. Ado.net[登录,增删改查,Get传值,全选,不选,批量删除,批量更新]

    [虽然说,开发的时候,我们可以使用各种框架,ado.net作为底层的东西,作为一个合格的程序员,在出问题的时候我们还是要知道如何调试] 一.增删改查 cmd.ExecuteReader();执行查询, ...

  9. MongoDB学习笔记~大叔分享批量添加—批量更新—批量删除

    回到目录 说它是批量操作,就是说将集合对象一次提交到服务器,并对数据进行持久化,如果您的代码是一次一次的提交,那不算是批量操作!在之前的mongodb仓储中并没有对批量更新和批量删除进行实现,而今天在 ...

  10. jdbc-批量插入、批量删除、批量更新

    一.JDBC的批量插入 JDBC批量插入主要用于数据导入和日志记录因为日志一般都是先写在文件下的等.    我用Mysql5.1.5的JDBC driver 分别对三种比较常用的方法做了测试   方法 ...

随机推荐

  1. PyCharm2018 不使用IPython 不成功--一直显示连接控制台

    每次关闭PyCharm时,都提示有后台任务在运行,一开始不知道怎么回事. 另外,发现底部的,python 控制台,启动pycharm时总有错误信息. 后来发现底部状态栏,显示1个 进程在运行. 2个地 ...

  2. Lombok和MapStruct冲突

    Lombok和MapStruct冲突导致无法生成正确的class文件. lombok自动生成getset等冗余代码. MapStruct对象copy.传统的BeanUtils.copy等利用的反射原理 ...

  3. Redis学习(黑马篇)

    1.redis是一个键值型数据库即在Redis内存的数据都是键值对的格式,如: 2.NOSQL非关系型数据库与MySQL关系型数据库对比: 非结构化类型分为:键值类型(Redis)(value支持多种 ...

  4. WSL/Ubutun安装GCC

    1.更新升级软件包 $ sudo apt-get update && sudo apt-get upgrade -y 2.清理关联软件包 $ sudo apt autoremove - ...

  5. OVS内核流表查询过程

    概括 现在的OVS使用microflow+megaflow缓存查询流表,ovs整体流程是从ovs_vport_receive(datapath/vport.c)开始,然后进入ovs_dp_proces ...

  6. Masa Framework源码解读-02缓存模块(分布式缓存进阶之多级缓存)

    序言 ​ 今天这篇文章来看看Masa Framework的缓存设计,上一篇文章中说到的MasaFactory的应用也会在这章节出现.文章中如有错误之处还请指点,咱们话不多说,直入主题. Masa Fr ...

  7. 声网Agora发布教育信息化解决方案 助力教育公平提效

    4月23日-25日,由中国教育装备行业协会主办的第79届教育装备展在厦门国际会展中心举办.作为赋能教育信息化的实时互动PaaS服务商,声网Agora应邀参会.展会现场,声网展示了基于实时音视频互动能力 ...

  8. java多线性--线程创建

    java多线性--线程创建 什么是多线程:不同的功能同时进行 Process(进程)与Thread(线程) 进程是执行程序的一次执行过程,是一个动态的概念.是系统分配资源的单位. 一个进程分为多个线程 ...

  9. FutureTask 类

    更多内容,前往IT-BLOG 一.什么是 Future和 FutureTask FutureTask 的 Future就源自于它的异步工作机制,如果我们在主线程中直接写一个函数来执行任务,这是同步的任 ...

  10. JSON 与 Java 对象之间的转化

    前言 在现在的日常开发中,不管前端还是后端,JSON 格式的数据是用得比较多的,甚至可以说无处不在. 接触最多的就是 POST 请求中传递的数据一般以 JSON 的格式放在请求体中,而且服务端各种 A ...