当前位置: 首页 > article >正文

PostgreSQL遍历所有的表并设置id为自增主键(基于自建函数)

 创建自定义函数

-- DROP FUNCTION public.create_seq_and_set_pkey(text);

CREATE OR REPLACE FUNCTION public.create_seq_and_set_pkey(histroy_table_name text)
RETURNS void
LANGUAGE plpgsql
NOT FENCED NOT SHIPPABLE
AS $function$
DECLARE
    max_id BIGINT;
    sequence_name TEXT;
BEGIN
    -- 获取当前表的最大id
    EXECUTE FORMAT('
        SELECT COALESCE(MAX(id), 0)
        FROM %I',
        histroy_table_name
    ) INTO max_id;

    RAISE NOTICE 'Max ID for table % is %', histroy_table_name, max_id;

    -- 生成序列名称
    sequence_name := histroy_table_name || '_id_seq';

    RAISE NOTICE 'Sequence name for table % is %', histroy_table_name, sequence_name;

    -- 检查序列是否存在
    IF EXISTS (SELECT 1 FROM pg_class WHERE relkind = 'S' AND relname = sequence_name) THEN
        -- 如果序列存在,则修改序列的起始值为 max_id + 1
        EXECUTE FORMAT('
            SELECT setval(%L, %s)',
            sequence_name,
            max_id + 1
        );

        RAISE NOTICE 'Updated sequence % to start from %', sequence_name, max_id + 1;
    ELSE
        -- 如果序列不存在,则创建序列并设置起始值为 1
        EXECUTE FORMAT('
            CREATE SEQUENCE %I START %s',
            sequence_name,
            1
        );

        RAISE NOTICE 'Created sequence % starting from 1', sequence_name;
    END IF;

    -- 检查 id 列是否已设置默认值,如果没有则设置默认值
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = histroy_table_name AND column_name = 'id' AND column_default IS NOT NULL) THEN
        EXECUTE FORMAT('
            ALTER TABLE %I
            ALTER COLUMN id SET DEFAULT nextval(%L)',
            histroy_table_name,
            sequence_name
        );

        RAISE NOTICE 'Set default value for id column in table % to nextval(%L)', histroy_table_name, sequence_name;
    ELSE
        RAISE NOTICE 'Default value for id column in table % already set', histroy_table_name;
    END IF;

    -- 检查主键是否已存在,如果不存在则添加主键
    IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE table_name = histroy_table_name AND constraint_type = 'PRIMARY KEY') THEN
        EXECUTE FORMAT('
            ALTER TABLE %I
            ADD PRIMARY KEY (id)',
            histroy_table_name
        );

        RAISE NOTICE 'Added primary key to table %', histroy_table_name;
    ELSE
        RAISE NOTICE 'Primary key already exists in table %', histroy_table_name;
    END IF;
END;
$function$;

单独执行示例

select create_seq_and_set_pkey('表名');

 遍历执行

使用方式:数据库命令行直接运行

DO $$
DECLARE
    table_name TEXT;
BEGIN
    -- 遍历 public 模式下的所有表
    FOR table_name IN (
        SELECT tablename
        FROM pg_tables
        WHERE schemaname = 'public'
		order by tablename
    )
    LOOP
        -- 调用函数 create_seq_and_set_pkey
        PERFORM create_seq_and_set_pkey(table_name);
    END LOOP;
END;
$$ LANGUAGE plpgsql;

遍历 public 模式下的所有表,并对每个表调用名为 create_seq_and_set_pkey 的函数。以下是对代码的详细解释:

  1. 声明部分 (DECLARE)

    • table_name TEXT;:声明一个变量 table_name,用于存储表名。

  2. BEGIN 和 END 之间的主体部分

    • 遍历表 (FOR 循环)

      • FOR table_name IN (...):使用 FOR 循环遍历 public 模式下的所有表。

      • SELECT tablename FROM pg_tables WHERE schemaname = 'public' ORDER BY tablename:从 pg_tables 系统表中选择 public 模式下的所有表名,并按表名排序。

    • 调用函数 create_seq_and_set_pkey

      • PERFORM create_seq_and_set_pkey(table_name);:对当前表名调用 create_seq_and_set_pkey 函数。PERFORM 语句用于执行函数并忽略其返回值。

整个存储过程的作用是遍历 public 模式下的所有表,并对每个表调用 create_seq_and_set_pkey 函数。

自定义函数剖析

create_seq_and_set_pkey 函数的功能是确保每个表具有一个序列,并且 id 列使用该序列作为默认值,同时确保表具有主键约束。函数接受一个表名作为参数,并执行以下操作:

  1. 获取当前表的最大 ID

    • 使用 EXECUTE FORMAT 语句动态执行 SQL 查询,获取表中的最大 id 值,并将结果存储在变量 max_id 中。

    • RAISE NOTICE 'Max ID for table % is %', histroy_table_name, max_id; 输出日志信息,显示表的最大 ID。

  2. 生成序列名称

    • 将表名与 _id_seq 拼接,生成序列名称,并存储在变量 sequence_name 中。

    • RAISE NOTICE 'Sequence name for table % is %', histroy_table_name, sequence_name; 输出日志信息,显示生成的序列名称。

  3. 检查序列是否存在

    • 使用 IF EXISTS 语句检查序列是否已经存在。

    • 如果序列存在,则使用 EXECUTE FORMAT 语句修改序列的起始值为 max_id + 1

    • RAISE NOTICE 'Updated sequence % to start from %', sequence_name, max_id + 1; 输出日志信息,显示更新后的序列起始值。

    • 如果序列不存在,则使用 EXECUTE FORMAT 语句创建序列,并设置起始值为 1。

    • RAISE NOTICE 'Created sequence % starting from 1', sequence_name; 输出日志信息,显示创建的序列起始值。

  4. 检查 id 列是否已设置默认值

    • 使用 IF NOT EXISTS 语句检查 id 列是否已设置默认值。

    • 如果没有设置默认值,则使用 EXECUTE FORMAT 语句设置 id 列的默认值为 nextval(sequence_name)

    • RAISE NOTICE 'Set default value for id column in table % to nextval(%L)', histroy_table_name, sequence_name; 输出日志信息,显示设置的默认值。

    • 如果已设置默认值,则输出日志信息,显示默认值已存在。

  5. 检查主键是否已存在

    • 使用 IF NOT EXISTS 语句检查主键是否已存在。

    • 如果不存在主键,则使用 EXECUTE FORMAT 语句添加主键约束。

    • RAISE NOTICE 'Added primary key to table %', histroy_table_name; 输出日志信息,显示添加的主键。

    • 如果主键已存在,则输出日志信息,显示主键已存在。


http://www.kler.cn/a/282892.html

相关文章:

  • CSS的综合应用例子(网页制作)
  • Python中的HTML
  • PdServer:调用MidjourneyAPI完成静夜思图文生成
  • Flink中自定义Source和Sink的使用
  • 力扣-Mysql-3308- 寻找表现最佳的司机(中等)
  • 【PowerHarmony】电鸿蒙学习记录-编写helloworld!
  • FineReport帆软报表:使用JAVA批量更新报表里的数据集连接名
  • 【python量化分析专题】最新整理的已经实测可用的各类免费股票数据接口之实时交易数据
  • 『大模型笔记』林纳斯·托瓦兹(Linux之父):谈论热议与人工智能的未来!
  • Linux 网络技术栈,看这篇就够了!!
  • 【ACM独立出版 | 厦大主办】第五届计算机科学与管理科技国际学术会议(ICCSMT 2024,10月18-20)
  • 基于web 在线影院系统网站设计与实现
  • 交通流量监测检测系统源码分享 # [一条龙教学YOLOV8标注好的数据集一键训练_70+全套改进创新点发刊_Web前端展示]
  • Qt 调用执行 Python 函数
  • zookeeper服务器动态上下线监听案例
  • 【MySQL数据库管理问答题】第4章 配置 MySQL
  • SpringBoot应用打成ZIP部署包
  • 18.神经网络 - 非线性激活
  • 【机器学习】梯度下降算法
  • 源码编译并安装Squid的方法
  • BEVDet4D:多帧时序信息融合方法详解
  • 富格林:正规方式顺利盈利出金
  • 性能测试的基本概念
  • Pycharm安装报错:Cannot detect a launch configuration 解决办法
  • 吴恩达机器学习笔记 四十五 基于内容的过滤的tensorFlow实现
  • 怎么解决 hash 碰撞,用 C++ 实现 hashMap?