概述

多表关联查询的时候会用到临时表插入数据,然后再用select查行查询,在往临时表里插入数据的时候,我们经常会用到判断如果临时表里有了这部分数据我们就要更新数据,如果临时表里没有这部分数据我们就要插入,这个时候可以怎么去实现呢?
下面介绍各类型数据库实现的大致方式。

一、存储过程实现

各类型数据库都可以通过存储过程实现,因为是共性问题,所以就放前面了,这里以mysql数据库的存储过程为例。

1、环境准备

--建表
create  table t1(
id  bigint(10),
name varchar(16),
sale bigint(10),
operatime datetime);
create table t2(
id  bigint(10),
name varchar(16),
sale bigint(20));-- 插入数据
INSERT into t1 values(1,"xiaohong",1000,now());
INSERT into t1 values(2,"xiaoming",500,now());
INSERT into t2 values(1,"xiaohong",300);
INSERT into t2 values(2,"xiaoming",400);
INSERT into t2 values(3,"xiaoxiao",900);

2、存储过程实现

delimiter $
CREATE PROCEDURE merge_t2_to_t1 () BEGIN
-- 定义需要插入从a表插入b表的过程变量
DECLARE _ID bigint(10);
DECLARE _NAME VARCHAR (16);
DECLARE _SALE VARCHAR (16);-- 游标遍历数据结束标志
DECLARE done INT DEFAULT FALSE;
-- 游标指向a表结果集第一条-1位置
DECLARE cur_account CURSOR FOR SELECT ID, NAME,SALE FROM t2;
-- 游标指向a表结果集最后一条加1位置 设置结束标志
DECLARE CONTINUE HANDLER FOR NOT FOUND  SET done = TRUE;
-- 打开游标
OPEN cur_account;
-- 遍历游标
read_loop :
LOOP
--  取值a表当前位置数据到临时变量FETCH NEXT FROM cur_account INTO _ID,_NAME,_SALE;-- 如果取值结束 跳出循环
IF done THEN LEAVE read_loop;
END IF;-- 当前数据做对比,如果b表存在则更新时间 不存在则插入
IF NOT EXISTS ( SELECT 1 FROM t1 WHERE ID = _ID AND NAME=_NAME ) THENINSERT INTO t1 (ID, NAME,sale,operatime) VALUES (_ID,_NAME,_sale,now());ELSE UPDATE t1  set sale = _sale WHERE ID = _ID AND NAME=_NAME;
END IF;END LOOP;
CLOSE cur_account;END $

3、调用存储过程

call merge_t2_to_t1();

二、sqlserver的merge into语法

在SQL Server 2008的时候微软增加了一个强大的语句Merge。

1、语法

MERGE 语句是首先对源表和目标表都进行完全表扫描,然后拿源表和目标表检查,匹配条件,若成立则执行SQL语句1,不成立则执行SQL语句2,最执行SQL语句3。
语法:

MERGE [ TOP ( expression ) [ PERCENT ] ] [ INTO ] <操作表> --即将做插入、更新、删除的表USING <源表或者数据集或者子查询> --用户提供匹配条件来源的集合或者表ON <匹配条件> --可以是任意有效的条件组合[ WHEN MATCHED [ AND <clause_search_condition> ]--匹配条件成立THEN <SQL语句1> ][ WHEN NOT MATCHED [ BY TARGET ] [ AND <clause_search_condition> ]--匹配条件不成立THEN <SQL语句2> ][ WHEN NOT MATCHED BY SOURCE [ AND <clause_search_condition> ]--目标变不存在而源表存在的数据THEN <SQL语句3> ]
;  -- 不要忘记分号

注意:
1)Merge操作的只是“操作表”,源表不会有任何变化
2)Merge的最后结尾必须是以分号结束的,不能忘了分号
3)语法严格要求关键字之间只能有一个英文空格,不能有多余的空格
4)不一定要把三个操作都写全,可以根据实际情况

2、实验

1)环境准备

--建表
create  table t1(
id   int,
name VARCHAR(16),
sale int,
Operatime date);
create  table t2(
id   int,
name VARCHAR(16),
sale int);-- 插入数据
INSERT into t1 values(1,'xiaohong',1000,sysdate);
INSERT into t1 values(2,'xiaoming',500,sysdate);
INSERT into t2 values(1,'xiaohong',300);
INSERT into t2 values(2,'xiaoming',400);
INSERT into t2 values(3,'xiaoxiao',900);
commit;


2)merge into实现

MERGE INTO t1  USING  t2
ON t1.id-t2.id
WHEN MATCHED Then UpDate set t1.sale=t2.sale
When Not Matched
When Not Matched then insert values(t2.id,t2.name,t2.sale,sysdate);
--Merge的最后结尾必须是以分号结束的,不能忘了分号 谨记:语法严格要求关键字之间只能有一个英文空格,不能有多余的空格

三、Oracle的merge into语法

1、语法

merge语法是根据源表对目标表进行匹配查询,匹配成功时更新,不成功时插入。

MERGE INTO [target-table] A USING [source-table sql] B ON([conditional expression] and [...]...)
WHEN MATCHED THEN
[UPDATE sql]
WHEN NOT MATCHED THEN
[INSERT sql]

2、实验

1)环境准备

--建表
create  table t1(
id   number,
name VARCHAR(16),
sale number,
Operatime date);
create  table t2(
id   number,
name VARCHAR(16),
sale number);-- 插入数据
INSERT into t1 values(1,'xiaohong',1000,sysdate);
INSERT into t1 values(2,'xiaoming',500,sysdate);
INSERT into t2 values(1,'xiaohong',300);
INSERT into t2 values(2,'xiaoming',400);
INSERT into t2 values(3,'xiaoxiao',900);
commit;


2)Oracle merge into实现

merge into t1 using t2 on (t1.id=t2.id) WHEN MATCHED THEN
update set t1.sale=t2.sale
WHEN NOT MATCHED THEN
insert values(t2.id,t2.name,t2.sale,sysdate);

四、mysql的on duplicate key update语法

mysql并没有oracle、mssql的merge into语法,但是有个on duplicate key update语法(不是标准的sql语法)可以实现merge into语法。
ON DUPLICATE KEY UPDATE为Mysql特有语法,使用时应多注意主键和插入值是否是我们想要插入或修改的key、Value。
创建表,注意要有一个唯一索引 new_code_index, 插入或者更新时,以此为标准。另外在高并发环境下,禁用insert into …on duplicate key update…,因为会造成mysql主从不一致。

1、相关语法

--单条记录下使用
--假如t1表的主键或者UNIQUE 索引是a,如果数据库里面已经存在a=1的记录则更新这条记录的c字段的值为原来值+1,然后返回值为2。
--如果不存在则插入a=1,b=2,c=3到数据库,然后返回值为1。
INSERT INTO t1(a,b,c) VALUES (1,2,3)   ON DUPLICATE KEY UPDATE c=c+1;
--多记录下使用
INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6)  ON DUPLICATE KEY UPDATE c=VALUES(c);

2、实验

1)环境准备

--建表
create  table t1(
id  bigint(10),
name varchar(16),
sale bigint(10),
operatime datetime,
UNIQUE KEY `idx_id` (`id`) USING BTREE
);
create table t2(
id  bigint(10),
name varchar(16),
sale bigint(20),
UNIQUE KEY `idx_id` (`id`) USING BTREE
);-- 插入数据
INSERT into t1 values(1,"xiaohong",1000,now());
INSERT into t1 values(2,"xiaoming",500,now());
INSERT into t2 values(1,"xiaohong",300);
INSERT into t2 values(2,"xiaoming",400);
INSERT into t2 values(3,"xiaoxiao",900);


2)on duplicate key update实现

insert into t1 select id,name,sale,now() from t2 on duplicate key update sale=values(sale);


结果:实现了将表t2更新到表t1中去,存在就更新,不存在就插入,
注意:id字段是主键或UNIQUE索引,不然只会插入t2表所有行数据

五、mysql的replace into语法

Mysql replace与replace into都是经常会用到的功能;replace其实是做了一次update操作,而不是先delete再insert;而replace into其实与insert into很像,但对于replace into,假如表中的一个旧记录与一个用于PRIMARY KEY或一个UNIQUE索引的新记录具有相同的值,则在新记录被插入之前,旧记录被删除。

1、相关语法

--前两种形式用的多些,对于那些没有给予值的列,MySQL将自动为这些列赋上默认值
replace into table(col, ...) values(...)
replace into table(col, ...) select ...
replace into table set col=value, ...

注意:
1)replace根据UNIQUE约束的字段(设置为Primary Key),确定被替换的是哪一条记录。如果不存在要替换的记录, 那么就会插入一条新的记录。
2)replace语句会删除原有的一条记录, 并且插入一条新的记录来替换原记录。
3)一般用replace语句替换一条记录的所有列, 如果在replace语句中没有指定某列, 在replace之后这列的值被置空。
4)replace语句不能根据where子句来定位要被替换的记录。
5)常见update写法:update table set col=col+1 where id=1;
使用replace into不支持这样的写法:replace into table set col=col+1,id=1;

2、实验

1)环境准备

--建表
create  table t1(
id  bigint(10),
name varchar(16),
sale bigint(10),
operatime datetime,
UNIQUE KEY `idx_id` (`id`) USING BTREE
);
create table t2(
id  bigint(10),
name varchar(16),
sale bigint(20),
UNIQUE KEY `idx_id` (`id`) USING BTREE
);-- 插入数据
INSERT into t1 values(1,"xiaohong",1000,now());
INSERT into t1 values(2,"xiaoming",500,now());
INSERT into t2 values(1,"xiaohong",300);
INSERT into t2 values(2,"xiaoming",400);
INSERT into t2 values(3,"xiaoxiao",900);

2)replace into实现

replace into t1 select id,name,sale,now() from t2;


结果:实现了将表t2更新到表t1中去,存在就更新,不存在就插入。

六、pg自定义函数实现

oracle数据库中有merge函数,可在插入数据前判断:如果指定列数据不存在,则正常插入数据;如果指定列数据存在,则将此条数据更新为插入的数据。 postgresql数据库中没有类似自带函数,只能自己实现此功能
以下方法只实现了oracle中merge函数的部分功能,而最大的问题是必须针对每个表创建自己的merge函数,比较适合在进行数据库迁移的时候配合外部表和触发器使用。

1、环境准备

--建表
create  table t1(
id  int PRIMARY KEY,
name varchar(16),
sale int,
operatime timestamp with time zone);-- 插入数据
INSERT into t1 values(1,'xiaohong',1000,now());
INSERT into t1 values(2,'xiaoming',500,now());
commit;

2、pg自定义函数实现

该函数基于表级别。

CREATE FUNCTION merge_db(id_new INT,name_new varchar(10),sale_new int) RETURNS VOID AS
$$
BEGIN
LOOPUPDATE t1 SET sale = sale_new WHERE id = id_new and name = name_new;IF found THENRETURN;END IF;
BEGININSERT INTO t1 VALUES (id_new,name_new,sale_new,now());RETURN;
EXCEPTION WHEN unique_violation THEN
-- do nothing
END;
END LOOP;
END;
$$
LANGUAGE plpgsql;

3、实现

使用merge函数插入key列字段已经在表中存在的数据

select merge_db(1,'xiaohong',400);
select merge_db(2,'xiaoming',300);
select merge_db(3,'xiaoxiao',700);
select * from t1;

七、PG的WITH Queries语法

PostgreSQL中不直接支持merge into这个语法,但PostgreSQL可以使用WITH Queries (Common Table Expressions)的方法实现相同的功能。

1、语法

主要是利用了postgresql的一个update特性—RETURNING,返回一个update的结果集,因为查询条件的存在(也因为它是主键,是唯一),就会将两张表重叠的部分给过滤出来,再用where not exists将这些重叠的部分给忽略掉,这样就将数据merge进去了。

[WITH with_queries] SELECT select_list FROM table_expression [sort_specification]

2、实验

1)环境准备

--建表
create  table t1(
id  int primary key,
name text,
sale int,
operatime timestamp
);
create  table t2(
id  int primary key,
name text,
sale int
);-- 插入数据
INSERT into t1 values(1,'xiaohong',1000,now());
INSERT into t1 values(2,'xiaoming',500,now());
INSERT into t2 values(1,'xiaohong',300);
INSERT into t2 values(2,'xiaoming',400);
INSERT into t2 values(3,'xiaoxiao',900);


2)with 实现
用t2 这张表去更新t1 ,会将test1中没有的数据插入

WITH upsert AS (UPDATE t1  SET sale = t2.sale  FROM t2  WHERE t1.id = t2.id  RETURNING t1.*)
INSERT INTO t1 SELECT id,name,sale,now() FROM t2
WHERE NOT EXISTS ( SELECT 1  FROM upsert b  WHERE t2.id = b.id);

八、pg的UPSERT语法

PostgreSQL 9.5 引入了一项新功能,UPSERT(insert on conflict do),当插入遇到约束错误时,直接返回,或者改为执行UPDATE。

1、语法

[ WITH [ RECURSIVE ] with_query [, ...] ]
INSERT INTO table_name [ AS alias ] [ ( column_name [, ...] ) ]  { DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query }  [ ON CONFLICT [ conflict_target ] conflict_action ]  [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]  where conflict_target can be one of:  ( { index_column_name | ( index_expression ) } [ COLLATE collation ] [ opclass ] [, ...] ) [ WHERE index_predicate ]  ON CONSTRAINT constraint_name  and conflict_action is one of:  DO NOTHING  DO UPDATE SET { column_name = { expression | DEFAULT } |  ( column_name [, ...] ) = ( { expression | DEFAULT } [, ...] ) |  ( column_name [, ...] ) = ( sub-SELECT )  } [, ...]  [ WHERE condition ]

2、实验

1)环境准备

--建表
create  table t1(
id  int primary key,
name text,
sale int,
operatime timestamp
);
create  table t2(
id  int primary key,
name text,
sale int
);-- 插入数据
INSERT into t1 values(1,'xiaohong',1000,now());
INSERT into t1 values(2,'xiaoming',500,now());
INSERT into t2 values(1,'xiaohong',300);
INSERT into t2 values(2,'xiaoming',400);
INSERT into t2 values(3,'xiaoxiao',900);


2)insert on implict实现

--不存在则插入,存在则更新
insert into t1 select id,name,sale,now() from t2 on conflict (id) do update set sale=excluded.sale;
--不存在则插入,存在则直接返回(不做任何处理)
insert into t1 select id,name,sale,now() from t2 on conflict (id) do nothing;

Oracle、MySQL、SqlServer、PG数据库merge into语法实现总结相关推荐

  1. mysql数据库迁移对比_数据库的迁移总结及区别比较(Oracle,MySQL,SQLServer)

    徐亮,2011-4-1 导言:最近的数据超市项目需要从SQLServer迁移到MySql.在之前并没有很多数据库迁移方面的经验,所以也不知道迁移需要花费多久,都要做什么工作.通过几天的工作,项目已经顺 ...

  2. Oracle,Mysql,Sqlserver数据库连接串(总爱忘,留着备用)

    2019独角兽企业重金招聘Python工程师标准>>> 首先选择合适自己数据库的驱动程序,这里提到的都是常用驱动. 连接Oracle数据库 获得Oracle的驱动程序包classes ...

  3. oracle mysql sqlserver对比_Mysql、Oracle、SqlServer的JDBC连接实现和对比(提供驱动包)...

    首先,我们需要准备数据库连接所需的jar包.目前mysql的驱动包可能比较好找,但是oracle和sqlserver的有很多,要找到能用的要花一点点心思,这里直接把下载地址和版本发送出来. Mysql ...

  4. oracle mssql 实例,oracle,mysql,SqlServer三种数据库的分页查询的实例

    MySql: MySQL数据库实现分页比较简单,提供了 LIMIT函数.一般只需要直接写到sql语句后面就行了. LIMIT子 句可以用来限制由SELECT语句返回过来的数据数量,它有一个或两个参数, ...

  5. Mysql、Oracle、SQLServer等数据库参考文档免费分享下载

    场景 MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统 ...

  6. java 获取oracle mysql sqlserver 链接 connection

    import java.sql.Connection; import java.sql.DriverManager; //获取sqlserver connection public static Co ...

  7. spring配置jdbc连接oracle,mysql,sqlserver

    2019独角兽企业重金招聘Python工程师标准>>> http://mvnrepository.com/ 这个网站可以查询所有maven库的最新版本 一.oracle maven库 ...

  8. mysql sqlserver schema_MySQL数据库数据迁移到SQLserver

    最近因工作需要,需要将mysql数据库迁移到sqlserver,仅仅是数据迁移,因此相对比较简单.对于mysql迁移到sqlserver,我们需要使用到mysql odbc驱动,然后透过sqlserv ...

  9. MySQL中删除数据库的基本语法格式为_《MySQL数据库》SQL简介、语法格式

    原标题:<MySQL数据库>SQL简介.语法格式 一.SQL的简介 结构化查询语言(Structured Query Language),简称SQL.它是专门用来访问数据库的标准编程语言. ...

最新文章

  1. 怎么在电脑上使用python-开始在 Windows 上使用 Python(初学者)
  2. 生产订单结算KKS1常见错误
  3. Qmake创建项目文件
  4. prefixspan java_PrefixSpan序列模式挖掘算法
  5. DM365视频处理流程/DM368 NAND Flash启动揭秘
  6. mysql性能结构优化原理_MySQL性能管理及架构设计(二):数据库结构优化、高可用架构设计、数据库索引优化...
  7. java 混码_kotlin java 混合代码 maven 打包实现
  8. 洛谷P1757 通天之分组背包 [2017年4月计划 动态规划06]
  9. css3新增了哪三种边框效果,怎么在CSS3中实现一个边框效果
  10. win10 安装oracle 11gR2_database(内附下载地址)
  11. waves效果器_学会EQ效果器,浑厚亮嗓又大气
  12. 2021年百度智能云服务器最新租用价格表
  13. Windows XP将显示桌面图标放到任务栏
  14. 王牌竞速安装后显示服务器维护,王牌竞速进不去游戏怎么办 如何解决进不去游戏...
  15. Echarts 横坐标时间轴,相同的年份只显示第一个,方案记录
  16. 126企业邮箱smtp服务器设置,网易企业邮箱新增超级邮件列表等功能
  17. 未来已来——云应用引擎CAE开启应用Serverless新时代
  18. java scanner的hasnext,Java Scanner hasNext()方法
  19. 【Linux】/etc/issue、/etc/issue.net和/etc/motd的区别
  20. 2015年心情随笔--周围太烦躁,我想静静

热门文章

  1. 好玩的智力测试题-精品
  2. JSP界面——背景图片
  3. 项目管理中的进度控制与目标计划
  4. pandas数据拼接
  5. OCO-2卫星数据批量化下载教程
  6. 回忆录——一份曾经面试“网易AI产品经理”的作品
  7. 访问者(vistor)模式
  8. 删除 Win10 资源管理器中的6个文件夹
  9. 认识常见壳与程序的特征
  10. h5支付——前端需要处理什么?