首页 > 数据库 >7种数据库的存在则更新,不存在则插入(UPSERT)SQL写法

7种数据库的存在则更新,不存在则插入(UPSERT)SQL写法

时间:2023-09-10 19:12:09浏览次数:45  
标签:INFO INSERT INTO WHEN UPDATE SQL MATCHED 写法 UPSERT

在工作中遇到了这么一个需求,在往数据库插入数据时,如果一条数据不存在则插入,如果存在(根据主键或唯一索引判断)则更新,也就是所谓的UPSERT操作。大部分数据库都没有UPSERT语句,不过他们都有一些SQL的写法来实现这样的操作。

1. MySQL

使用ON DUPLICATE KEY UPDATE,如果要插入这条数据将导致唯一索引冲突或主键冲突,则会对原有数据进行UPDATE操作,否则进行INSERT操作。

假设表t1中a是主键,如:

INSERT INTO t1 (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;

UPDATE后可以接多个列,如:

INSERT INTO t1 (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE b=2, c=3;

对于多行数据可以这么写(采用别名):

INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new
  ON DUPLICATE KEY UPDATE c = new.a+new.b;

注:如果没有主键或唯一索引,每次都会INSERT,永远不会UPDATE。
如果表中有多个唯一索引,并且有多行都匹配上了,也只会更新一行,所以不要在有多个唯一索引的表中使用ON DUPLICATE KEY UPDATE。

2. Oracle

使用MERGE INTO,根据给定的列的值来决定INSERT还是UPDATE,用于判断的列可以不是主键。

MERGE INTO ALERT_INFO
USING DUAL
ON (ALERT_INFO.ID = '7')
WHEN NOT MATCHED
    THEN
    INSERT (ID,CONTENT) VALUES ('7','A7')
WHEN MATCHED
    THEN
    UPDATE SET CONTENT = 'A7';


MERGE INTO ALERT_INFO
USING DUAL
ON (ALERT_INFO.CONTENT = 'AA6')
WHEN NOT MATCHED
    THEN
    INSERT (ID,CONTENT) VALUES ('6','AA5')
WHEN MATCHED
    THEN
    UPDATE SET ID = '6';

3. SqlServer

使用MERGE INTO,根据给定的列的值来决定INSERT还是UPDATE,用于判断的列可以不是主键。
注:官方文档说这种用法可能带来并发问题。

MERGE INTO xh.dbo.hhhh AS tgt  
USING (VALUES ('Recommendation222',111), ('Review222', 211),
              ('Internet', 311))  
       as src (NewName, NewReasonType)  
ON tgt.aaa = src.NewName  
WHEN MATCHED THEN  
UPDATE SET bbb = src.NewReasonType  
WHEN NOT MATCHED BY TARGET THEN  
INSERT (aaa, bbb) VALUES (NewName, NewReasonType);

4. PostgreSQL

指定主键/唯一索引的列决定INSERT还是UPDATE
注:官方文档说这种用法是原子的
假设在public这个schema下的表student中,id是主键

INSERT INTO public.student (id, name, description)
    VALUES (5, 'Gizmo Transglobal', 'xxx'), (6, 'Associated Computing, Inc', 'xxxxx')
    ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, description=EXCLUDED.description;

5. 达梦(DM)

使用MERGE INTO,根据给定的列的值来决定INSERT还是UPDATE,用于判断的列可以不是主键。
与Oracle语法相同

MERGE INTO ALERT_INFO
USING DUAL
ON (ALERT_INFO.ID = '1')
WHEN NOT MATCHED
    THEN
    INSERT (ID,CONTENT) VALUES ('1','A1')
WHEN MATCHED
    THEN
    UPDATE SET CONTENT = 'A1';

MERGE INTO ALERT_INFO
USING DUAL
ON (ALERT_INFO.CONTENT = 'AA6')
WHEN NOT MATCHED
    THEN
    INSERT (ID,CONTENT) VALUES ('6','AA5')
WHEN MATCHED
    THEN
    UPDATE SET ID = '6';

6. 人大金仓(KingBase)

使用MERGE INTO,根据给定的列的值来决定INSERT还是UPDATE,用于判断的列可以不是主键。
与Oracle语法相同

MERGE INTO ALERT_INFO
USING DUAL
ON (ALERT_INFO.ID = '1')
WHEN NOT MATCHED
    THEN
    INSERT (ID,CONTENT) VALUES ('1','A1')
WHEN MATCHED
    THEN
    UPDATE SET CONTENT = 'A1';

MERGE INTO ALERT_INFO
USING DUAL
ON (ALERT_INFO.CONTENT = 'AA6')
WHEN NOT MATCHED
    THEN
    INSERT (ID,CONTENT) VALUES ('6','AA5')
WHEN MATCHED
    THEN
    UPDATE SET ID = '6';

7. 南大通用(GBase8s)

使用MERGE INTO,根据给定的列的值来决定INSERT还是UPDATE,用于判断的列可以不是主键。
与Oracle语法相同

MERGE INTO ALERT_INFO
USING DUAL
ON (ALERT_INFO.ID = '1')
WHEN NOT MATCHED
    THEN
    INSERT (ID,CONTENT) VALUES ('1','A1')
WHEN MATCHED
    THEN
    UPDATE SET CONTENT = 'A1';

MERGE INTO ALERT_INFO
USING DUAL
ON (ALERT_INFO.CONTENT = 'AA6')
WHEN NOT MATCHED
    THEN
    INSERT (ID,CONTENT) VALUES ('6','AA5')
WHEN MATCHED
    THEN
    UPDATE SET ID = '6';

更详细的介绍请进入参考资料中的官方文档查看

参考资料:

MySQL官方文档:
https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html
Oracle官方文档:
https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/MERGE.html#GUID-5692CCB7-24D9-4C0E-81A7-A22436DC968F
SqlServer官方文档:
https://learn.microsoft.com/zh-cn/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16
PostgreSQL官方文档:
https://www.postgresql.org/docs/15/sql-insert.html
达梦官方文档:
https://eco.dameng.com/document/dm/zh-cn/sql-dev/practice-dml-operation.html
人大金仓官方文档:
https://help.kingbase.com.cn/v8/development/sql-plsql/sql/SQL_Statements_10.html#merge
南大通用官方文档:
https://cdn.gbase.cn/products/27/b--vfeeESpHTsMJy2SZ0Y-GBase 8s V8.8 SQL 指南:语法.pdf

标签:INFO,INSERT,INTO,WHEN,UPDATE,SQL,MATCHED,写法,UPSERT
From: https://www.cnblogs.com/lambdadog/p/17691654.html

相关文章

  • Navicat连接Docker创建的MySQL运行实例
    一步步教你在Docker中安装MySQL(qq.com)Docker部署MySql应用-魔鬼YU天使-博客园(cnblogs.com)拉取MySQL镜像我们可以通过Docker提供的命令,直接从DockerHub上拉取MySQL的官方镜像。打开终端,输入如下命令:dockerpullmysql:8.0其中,:8.0表示我们需要下载的MySQL版本,你也......
  • linux7.X二进制方式安装MySQL5.7.X
    概述系统环境服务器型号VMwareVirtualPlatform操作系统版本RHEL7.6x86_64主机名linuxpg51PubIP192.168.115.51数据库安装版本mysqlVer14.14Distrib5.7.30,forlinux-glibc2.12(x86_64)usingEditLinewrapper安装路径规划[mysql@linuxpg51/]$tree-L1/mysql/mysq......
  • MongoDB下载和可视化工具NoSQL Manager for MongoDB 软件的下载,连接数据库
      在官网下载MongoDB的版本为4.0.28,之前试了好几个高版本和低版本,都不行,最后,4.0.28版本好了。下载网页:https://www.mongodb.com/try/download/community 安装和配置环境变量的方法一搜就行了,不难。打开安装MongoDB的bin路径,输入cmd,打开命令提示符,再输入红色圈住的命令,看是......
  • MySQL基础
    要学习数据库首先要先搞清楚三个概念数据库(DB):是存储数据的仓库数据库管理系统(DBMS):管理数据库的大型软件SQL:通过SQL操作数据库管理系统操作数据库,对数据库进行增删改查等由此我们可以知道数据库就是安装在操作系统之上的数据仓库,用于存储数据。我们也先认识一个概念->关系型数据......
  • postgresql数据库安装日志解析插件wal2json
    postgresql数据库安装日志解析插件wal2json一、编译安装wal2json插件cdwal2jsonexportPATH=/data/home/fei.yang4/moudle/postgresql/bin:$PATHmakemakeinstall二、直接导入wal2json插件查看pg进程确定pgsql库和配置文件存放目录ps-ef|greppostgresqlubuntu24975248......
  • 【k8s】k8s构建mysql双主集群
    背景当前很多开源系统都是基于k8s,而部署时会遇到组件包含mysql的情况。理想的情况下,是将mysql迁移到云上托管。但实际情况可能比较复杂,比如这个开源框架需要mysql的DML权限,但是公司DBA不提供;而基于k8s部署mysql的问题是,这个mysql集群往往是单点的。一般mysql会依赖于一个本地挂......
  • Windows安装MySQL Community Server 8.1.0 Innovation
    检查是否安装按win+r打开运行,输入services.msc回车在服务列表中查找mysql服务,如果存在mysql服务,说明已经安装mysql。反之,则说明没有安装了mysql服务。下载并安装下载链接:https://dev.mysql.com/downloads/mysql/MySQLCommunityServer8.1.0Innovation有msi版本......
  • 【高级】MySQL主从复制
    【一】引入之前做过redis的主从,很简单mysql稍微复杂一些,搭建mysql主从的目的是?读写分离单个实例并发量低,提高并发量只在主库写,读数据都去从库----》读多写少读写分离通过将读操作分发到从库,可以分摊主库的读负载,提高整体的并发处理能力。主库只需处理写操作,从库......
  • MySQL面试问题集锦
    1、请简要说明一条SQL语句的执行过程。参照:深度好文:MySQL架构(baidu.com)一文读懂MySQL查询语句的执行过程(taodudu.cc)MySQLServer架构自顶向下大致可以分网络连接层、服务层、存储引擎层和系统文件层。2、mysql有关权限的表都有哪几个MySQL服务器通过权限表来控制用户对......
  • 达梦数据库教程:DM8查看试用版证书到期时间SQL
    达梦数据库试用期限为一年,不是以本地安装时间算起的,是安装包已经把开始时间和截止时间内置好了,官网定期更新安装包版本。如果想看你安装的达梦啥时候到期,执行以下语句即可select*fromv$license;查询出记录后,看EXPIRED_DATE这个字段就是截止日期了。一定要在截止前把数据库迁移或......