Postgresql数据库中通过函数实现将不确定列的数据插入到表中

news2024/12/25 9:22:28

在数据库操作中,经常会遇到需要将不确定列的数据插入到表中的情况。这个文章将详细介绍如何在 PostgreSQL 中通过函数来实现这一需求,记录一下。

一、需求概述

在实际应用中,可能会接收到一个包含数据的 JSON 字符串,需要将其插入到指定表中。同时,要处理表的主键问题,确保在数据中没有主键值时能自动生成并添加。此外,还需要考虑表可能位于不同的模式(schema)下,以及后续的数据更新操作。

二、实现分析

为了实现上述需求,需要利用 PostgreSQL 丰富的函数和操作符来处理 JSON 数据、获取表结构信息、生成主键值以及构建和执行 SQL 语句。

三、实现步骤

第一步:获取表的所有字段

使用 information_schema.columns 表获取指定表和模式下的所有列名,并存储在 all_column_names 数组中。

第二步:查找主键字段及数据类型

通过查询 information_schema.key_column_usage 和相关表来确定主键列名和数据类型。

第三步:如果 Json 没有主键字段,则给 Json 增加主键字段

将输入的 JSON 字符串转换为 JSONb 类型,并检查主键列在数据中是否存在。如果不存在且主键为整数类型,从表中获取最大值并加 1 作为主键值;如果主键为其他类型,则生成一个随机 UUID 作为主键值。之后创建包含主键的新 JSON 数据并与原数据合并。

第四步:构建插入语句的列和值

接下来,构建插入语句的列和值部分。遍历 all_column_names 数组,只添加数据中存在值的列到插入语句中。

第五步:插入

最后,执行构建好的插入语句,将数据插入到表中。

四、测试

为了验证函数的正确性,进行如下测试操作:

CREATE TABLE test_table (
    id VARCHAR(50) PRIMARY KEY,
    name VARCHAR(50),
    age INT
);

CREATE TABLE test_table2 (
    id int PRIMARY KEY,
    name VARCHAR(50),
    age INT
);

SELECT insert_data_to_table('{"name": "Alice", "age": 25,"id": "55655655" }', 'test_table');
SELECT insert_json_data('{"name": "Aliceb", "age": 26}', 'test_table');
SELECT insert_json_data('{"name": "Alicec", "age": 27}', 'test_table');
SELECT insert_json_data('{}', 'test_table2');

插入后的效果

五、结果

经过测试,上述函数能够成功地将不确定列的数据插入到表中,并根据给定的条件进行更新操作。在实际应用中,我们可以根据具体的业务需求灵活调整函数的参数和逻辑,以满足更多复杂的场景。

六、附:完整的函数

-- 插入数据函数
CREATE OR REPLACE FUNCTION insert_data_to_table(json_string TEXT, tName TEXT, SchemaName TEXT DEFAULT 'public')
RETURNS VOID AS $$
DECLARE
    all_column_names TEXT[];
    primary_key_column_name TEXT;
    primary_key_data_type TEXT;
    json_data JSONb;
    new_json_data jsonb;
    insert_statement TEXT;
    key_value TEXT;
    max_value INT;  -- 用于存储主键的最大值
BEGIN
    -- 第一步:获取表的所有字段
    SELECT array_agg(column_name) INTO all_column_names
    FROM information_schema.columns
    WHERE table_name = tName AND table_schema = SchemaName;

    -- 第二步:查找主键字段及数据类型
    SELECT kcu.column_name, data_type INTO primary_key_column_name, primary_key_data_type
    FROM information_schema.key_column_usage kcu
    JOIN information_schema.columns col ON kcu.column_name = col.column_name
    WHERE kcu.table_name = tName AND col.table_schema = SchemaName AND kcu.constraint_name IN 
        (SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = tName AND table_schema = SchemaName AND constraint_type = 'PRIMARY KEY');

    -- 第三步:如果 Json 没有主键字段,则给 Json 增加主键字段
    json_data := json_string::JSONb;
    IF primary_key_column_name IS NOT NULL AND json_data ->> primary_key_column_name IS NULL THEN
        IF primary_key_data_type = 'integer' THEN
            -- 获取主键的最大值
            EXECUTE 'SELECT coalesce(max(' || primary_key_column_name || '), 0) + 1 FROM ' || SchemaName || '.' || tName INTO max_value;
            key_value := max_value;  -- 使用获取到的最大值加 1 作为主键值
        ELSE
            key_value := gen_random_uuid()::TEXT;
        END IF;
        new_json_data := concat('{', '"', primary_key_column_name, '": "', key_value, '"}')::jsonb;
        json_data := (new_json_data || json_data);
    END IF;

    -- 第四步:构建插入语句的列和值
    insert_statement := 'INSERT INTO ' || SchemaName || '.' || tName || ' (';
    FOR i IN 1..array_length(all_column_names, 1) LOOP
        IF json_data ->> all_column_names[i] IS NOT NULL THEN
            insert_statement := insert_statement || all_column_names[i] || ', ';
        END IF;
    END LOOP;
    insert_statement := substring(insert_statement, 1, length(insert_statement) - 2) || ') VALUES (';
    FOR i IN 1..array_length(all_column_names, 1) LOOP
        IF json_data ->> all_column_names[i] IS NOT NULL THEN
            insert_statement := insert_statement || quote_literal(json_data ->> all_column_names[i]) || ', ';
        END IF;
    END LOOP;
    insert_statement := substring(insert_statement, 1, length(insert_statement) - 2) || ')';

    -- 第五步:插入
    RAISE NOTICE '%', insert_statement;
    EXECUTE insert_statement;
END;
$$ LANGUAGE plpgsql;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1990775.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

体外诊断 | 从说明书看研发:阳性判断值研究

来源于《甲型流感病毒、乙型流感病毒和新型冠状病毒(2019-nCoV) 核酸检测试剂盒(PCR-荧光探针法)审评报告》(CSZ2200276) 来源于《血清淀粉样蛋白A/C 反应蛋白二联检测试剂盒(荧光免…

vue3--实现vue2插件JSONPathPicker的路径获取功能

背景 最近在进行vue2项目升级为vue3。 在项目中需要获取json某些字段的路径,vue2中使用JSONPathPicker ,但是该插件不支持vue3,vue3中也没有相应的模块有该功能。 实现目标: 原vue2中JSONPathPicker实现的功能: 查…

多智能体协作之 AutoGen Studio

目录 一、AutoGen Studio 安装 二、AutoGen Studio 使用 2.1 Skills 2.1.1 generate_and_save_images 2.1.2 generate_and_save_pdf 2.2 Models 2.3 Agents 2.4 Workflows 2.5 Playground 本文主要对 AutoGen Studio 进行介绍。 一、AutoGen Studio 安装 通过 pip 进…

PCIe 物理尺寸和形状

PCIe 物理尺寸和形状 1. PCIe Riser (PCIe 插槽)2. Riser 卡与 PCIe 卡2.1. PCIe 卡尺寸 3. Form factors (规格,物理尺寸和形状)4. Peripheral Component Interconnect Express (PCI Express, PCIe or PCI-e)5. HHHL and FHHL5.1. HHHL DPU Layout and Interface I…

TM1652段码屏芯片全解析——概况,性能,MCU连接,样例代码

首先,作为四年前就有的LED段码控制芯片,相关的资料及样例程序少的可怜。硬件驱动 作为固定使用的 软件资源,其共享性远低于软件领域的驱动库。人的才智不应浪费在这种不具创造性的重复实验上。 要点总结: TM1652概述&#xff1a…

k-means算法原理

1 算法简介 k-means(k均值)算法由不同学者于20世纪50-60年代在不同领域提出的一种聚类算法。随后该算法不断得到了改进,成为了一种非常广泛应用的聚类算法。k-means算法是将样本按距离划分为k个簇的一种聚类算法。 2 算法的基本原理 2.1 相…

TypeError: Cannot read property ‘xxx‘ of undefined

1.首先贴出控制台的报错信息 2.从报错信息看的一脸疑惑,xxx属性或方法确实定义了,引入后怎么就报错了,一开始还怀疑是小程序缓存导致的,清理缓存重新编译还是报错,然后怀疑是分包导致的,后来看到我的代码是…

一、stm32在cubemx配置硬件crc与rng测试演示

一、crc配置 1、配置crc界面 2、crc主要调用的函数 这两个都可以生成crc,存在一些区别,但都可以生成crc其结果都是一样的。 二、rng配置 1、rng配置的界面 2、rng生成函数 这三个函数都可以生成随机数,其中开启中断后可调用回调函数&am…

在Linux中宏观的看待线程

线程一旦被创建,几乎所有的资源都是被所有的线程共享的。线程也一定要有自己私有的资源,什么样的资源应该是线程私有的? 1.PCB属性私有 2.要有一定的私有上下文结构 3.每个线程都要有独立的栈结构 ps -aL ##1. Linux线程概念 ###什么是线程…

深度学习每周学习总结N6:使用Word2vec实现文本分类

🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 | 接辅导、项目定制 目录 0. 总结:1.加载数据2. 构建词典3. 生成数据批次和迭代器4.模型搭建及初始化5. 定义训练与评估函数6. 拆分数据集并运行模…

界面控件(无ui文件)

目录 菜单栏 工具栏 状态栏 停靠部件和核心部件 菜单栏 MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {// 菜单栏,获取当前窗口的菜单栏,没有会自动创建一个QMenuBar *mb this->menuBar();// 添加菜单QMenu *menuFile mb-&g…

【ML】Pre-trained Language Models及其各种微调模型的实现细节和特点

Pre-trained Language Models及其各种微调模型的实现细节和特点 1. Pre-trained Language Models2. semi-supervised Learning3. zero-shot4. Parameter-Efficient Fine-Tuning4.1 含义:4.2 实现方式: 5. LoRA5.1 LoRA 的主要特点:5.2 LoRA 的…

【QT 5 QT 6 构建工具qmake-cmake-和-软件编译器MSVCxxxvs MinGWxxx说明】

【QT 5报错:/xxx/: error: ‘class Ui::frmMain’ has no member named ‘xxx’-和-软件编译器MSVCxxxvs MinGWxxx说明】 1、前言2 、qt 中 Qmake CMake 和 QBS1-qmake2-Cmake3-QBS4-官网一些说法5-各自特点 3、软件编译套件1-Desktop Qt 6.7.2 llvm-mingw 64-bit2-…

SpringBoot排除默认日志框架

默认用的logback application.properties中的配置无需改变,自动装配会根据条件(哪个日志的.class是否存在) 进行切换 只要切换日志配置文件就好 比如原来使用的logback-spring.xml换成log4j2-spring.xml 日志文件网上找找

Flink-DataWorks第三部分:数据集成(第59天)

系列文章目录 2.4 任务配置方式 2.4.1 DataStudio侧离线同步 2.4.1.1 开发流程概览 2.4.1.2 步骤一:新建离线同步节点 2.4.1.3 步骤二:配置同步网络链接 2.4.1.4 步骤三:配置数据来源与去向 2.4.1.5 步骤四:配置字段映射关系 2.4…

C:野指针介绍(定义、危害、规避)以及野指针与空指针的区分

目录 1、野指针 1.1 野指针的成因 1.指针未初始化 2.指针越界访问 3.指针指向的空间释放 1.2 野指针的危害 1.3 如何规避野指针 1. 指针初始化 2. 小心指针越界 3.指针变量不使用就及时赋上NULL 4. 指针使用前检查是否是空指针 5. 避免返回局部变量的地址 1.4 区…

微信小程序【五】摇骰子

摇骰子 一、dice.js二、dice.json三、dice.wxml四、dice.wxss 效果简述:点击设置“骰子个数”,喝一杯前,先摇一摇。 骰子图片命名示例: 1.png、2.png 一、dice.js Page({data: {numDice: 1, // 初始化骰子数diceImages: [],dic…

【iOS多线程(二)】GCD其他方法详解

GCD其他方法 dispatch_semaphore (信号量)什么是dispatch_semaphore(信号量)?dispatch_semaphore主要的三个方法dispatch_semaphore主要作用线程安全线程同步 dispatch_afterdispatch_time_t 两种形式 GCD 一次性代码(只执行一次&#xff09…

电脑维修店的主题源码 简洁wordpress企业主题模版下载

简洁wordpress企业主题,一个简洁的电脑维修店的主题 源码下载:https://download.csdn.net/download/m0_66047725/89612932 更多资源下载:关注我。

【深度学习】TTS,CosyVoice,推理部署的代码原理讲解分享

文章目录 demo代码加载配置文件speech_tokenizer_v1.onnx(只在zero_shot的时候使用)campplus.onnx(只为了提取说话人音色embedding)`campplus_model` 的作用代码解析具体过程解析总结示意图CosyVoiceFrontEndCosyVoiceModel推理过程总体推理过程推理速度很慢: https://git…