批量更新Postgresql的序列
序列(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();
注意:
- 格式化字符
%s与%I有不同,在 PostgreSQL 中,%I是格式化字符串中的一个占位符,用于在 SQL 查询中引用标识符(如列名、表名等)。它类似于%s占位符,但是会将参数中的标识符转换为带有双引号的字符串,以防止 SQL 注入攻击。对于setval参数,需要灵活选择使用%s与%I- 函数使用is_identity()来判断是否为自增的列。
注意事项
在更新表的序列时,请注意以下几点:
- 序列是全局对象,因此在更新前,请确保没有其他用户当前正在使用该序列。
- 一定多检查,不要更新错误的序列。
- 操作之前先备份数据。
批量更新Postgresql的序列的更多相关文章
- SQL 将2张不相关的表拼接成2列,批量更新至另一张表
update SO_Master set LotteryNo=t2.LotteryNo,UpdateTime=GETDATE() --select sm.LotteryNo,sm.SysNo,t2.L ...
- spring data jpa开启批量插入、批量更新
spring data jpa开启批量插入.批量更新 原文链接:https://www.cnblogs.com/blog5277/p/10661096.html 原文作者:博客园--曲高终和寡 *** ...
- 转://批量更新sequence的存储
前言: ORACLE的序列(SEQUENCE)A SCHEMA OBJECT THAT GENERATES A SERIAL LIST OF UNIQUE NUMBERS FOR TABLE COLU ...
- FreeSql (十四)批量更新数据
FreeSql支持丰富的更新数据方法,支持单条或批量更新,在特定的数据库执行还可以返回更新后的记录值. var connstr = "Data Source=127.0.0.1;Port=3 ...
- update批量更新某一列成其它列对应的值【原】
update批量更新某一列成其它列对应的值 postgresql 标准sql语句 update AA set name = BB.name , AA.sex = BB.sex from BB wher ...
- SQL批量更新 关系表更新
很多人在做数据的批量更新时..如果更新的内容是从其他表查出来的..很容易这么写.. UPDATE TABLE1 SET COLUMN1=(SELECT SUM(SOMETHING) FROM TABL ...
- [PDO绑定参数]使用PHP的PDO扩展进行批量更新操作
最近有一个批量更新数据库表中某几个字段的需求,在做这个需求的时候,使用了PDO做参数绑定,其中遇到了一个坑. 方案选择 笔者已知的做批量更新有以下几种方案: 1.逐条更新 这种是最简单的方案,但无疑也 ...
- Ado.net[登录,增删改查,Get传值,全选,不选,批量删除,批量更新]
[虽然说,开发的时候,我们可以使用各种框架,ado.net作为底层的东西,作为一个合格的程序员,在出问题的时候我们还是要知道如何调试] 一.增删改查 cmd.ExecuteReader();执行查询, ...
- MongoDB学习笔记~大叔分享批量添加—批量更新—批量删除
回到目录 说它是批量操作,就是说将集合对象一次提交到服务器,并对数据进行持久化,如果您的代码是一次一次的提交,那不算是批量操作!在之前的mongodb仓储中并没有对批量更新和批量删除进行实现,而今天在 ...
- jdbc-批量插入、批量删除、批量更新
一.JDBC的批量插入 JDBC批量插入主要用于数据导入和日志记录因为日志一般都是先写在文件下的等. 我用Mysql5.1.5的JDBC driver 分别对三种比较常用的方法做了测试 方法 ...
随机推荐
- C# 自定义控件如何正确的继承父类
C# 自定义控件可以分为三类: 复合控件:基本控件组合而成.应当继承自 UserControl 扩展控件:继承基本控件,扩展一些属性和事件.比如继承 Button 自定义控件:直接继承自 Contro ...
- C语言基础编程题
//1.ASCII码值 ->相应字符 #include <stdio.h> int main() { int asc; scanf("%d",&asc); ...
- Mysql_5.7编译部署
自述 - 概述:数据库是"按照数据结构来组织.存储和管理数据的仓库".是一个长期存储在计算机内的.有组织的.可共享的.统一管理的大量数据的集合:本文主要介绍mysql_5.7的部署 ...
- Vue 使用插件nprogress页面加载进度条
下载 npm i nprogress 在main.js中引入: import App from './App' import VueRouter from 'vue-router' import ro ...
- gstreamer样例
#!/bin/bash xrandr -s 0 --output DSI-1 xrandr -s 0 --output HDMI-1 xrandr --fb 1024x600 --output DSI ...
- SQL 2019 卸载方法
一.关闭服务 1. win+r services.msc 打开服务,关闭与SQL有关的服务内容. 二.卸载应用 1.win+r control 打开控制面板---卸载程序---卸 ...
- P2671 [NOIP2015 普及组] 求和
[NOIP2015 普及组] 求和 题目背景 NOIP2015 普及组 T3 题目描述 一条狭长的纸带被均匀划分出了\(n\)个格子,格子编号从\(1\)到\(n\).每个格子上都染了一种颜色\(co ...
- VSCODE C# 运行 找不到任务"BUILD"----C#常用命令
使用 Visual Studio Code 创建 .NET 类库 - .NET | Microsoft Docs 安装vscode.vscode c#相关拓展.MINIGW64 1.创建文件夹 2.用 ...
- markdown常用语法及Typora的使用
一.markdown markdown简介 markdown是一种文档格式,后缀名为.md.markdown非常适于写博客,基本所有博客网站都支持markdown语法格式. 1.标题 mark ...
- ElasticSearch 实现分词全文检索 - match、match_all、multimatch查询
目录 ElasticSearch 实现分词全文检索 - 概述 ElasticSearch 实现分词全文检索 - ES.Kibana.IK安装 ElasticSearch 实现分词全文检索 - Rest ...