当前位置:首页 » 编程语言 » sqlmergeinto语法
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

sqlmergeinto语法

发布时间: 2023-03-19 06:53:52

‘壹’ DB2中merge相关用法,请举例说明

在数据仓库中的转换和装载过程中,经常会使用MERGE语句,这里简单总结一下。MERGE语句是Oracle9i新增的语法,用来合并UPDATE和INSERT语句。通过MERGE语句,根据一张表或子查询的连接条件对另外一张表进行查询,连接条件匹配上的碧纯销进行UPDATE,无法匹配的执行INSERT。这个语裤漏法仅需要一次全表扫描就完成了全部工作,执行效率要高于INSERT+UPDATE。 下面看个具体的例子: sql> CREATE TABLE T AS SELECT ROWNUM ID, A.* FROM DBA_OBJECTS A;表已创建。SQL> CREATE TABLE T1 AS 2 SELECT ROWNUM ID, OWNER, TABLE_NAME, CAST('TABLE' AS VARCHAR2(100)) OBJECT_TYPE3 FROM DBA_TABLES;表已创建。SQL> MERGE INTO T1 USING T 2 ON (T.OWNER = T1.OWNER AND T.OBJECT_NAME = T1.TABLE_NAME AND T.OBJECT_TYPE = T1.OBJECT_TYPE)3 WHEN MATCHED THEN UPDATE SET T1.ID = T.ID4 WHEN NOT MATCHED THEN INSERT VALUES (T.ID, T.OWNER, T.OBJECT_NAME, T.OBJECT_TYPE);6165 行已合并。SQL>悔游 SELECT ID, OWNER, OBJECT_NAME, OBJECT_TYPE FROM T2 MINUS3 SELECT * FROM T1;未选定行MERGE语法其实很简单,下面稍微修改一下例子。SQL> DROP TABLE T;表已丢弃。SQL> DROP TABLE T1;表已丢弃。SQL> CREATE TABLE T AS SELECT ROWNUM ID, A.* FROM DBA_OBJECTS A;表已创建。SQL> CREATE TABLE T1 AS SELECT ROWNUM ID, OWNER, TABLE_NAME FROM DBA_TABLES;表已创建。SQL> MERGE INTO T1 USING T 2 ON (T.OWNER = T1.OWNER AND T.OBJECT_NAME = T1.TABLE_NAME)3 WHEN MATCHED THEN UPDATE SET T1.ID = T.ID4 WHEN NOT MATCHED THEN INSERT VALUES (T.ID, T.OWNER, T.OBJECT_NAME);MERGE INTO T1 USING T*ERROR 位于第 1 行:ORA-30926: 无法在源表中获得一组稳定的行这个错误是使用MERGE最常见的错误,造成这个错误的原因是由于通过连接条件得到的T的记录不唯一。最简单的解决方法类似:SQL> MERGE INTO T1 2 USING (SELECT OWNER, OBJECT_NAME, MAX(ID) ID FROM T GROUP BY OWNER, OBJECT_NAME) T 3 ON (T.OWNER = T1.OWNER AND T.OBJECT_NAME = T1.TABLE_NAME)4 WHEN MATCHED THEN UPDATE SET T1.ID = T.ID5 WHEN NOT MATCHED THEN INSERT VALUES (T.ID, T.OWNER, T.OBJECT_NAME);5775 行已合并。本文来自CSDN博客,转载请标明出处: http://blog.csdn.net/levma/archive/2007/06/18/1656396.aspx

‘贰’ SQL B表内容添加到A表

应你的要求,我来了,希望这次给你想要的解答。

我的回答是基于oracle数据库给出的解答,
其他的数据库,则部分实现方式需要改动

这个问题包含2个部分:一,执行的SQL语句怎么写;二,调用的批处理语句怎么写。

**********************************
首先,我使用的SQL用到了merge语句,但是它不属于标准SQL,是oracle自己的SQL语法,如下:
merge into A using B
on A.column1=B.column1(此处可改成合适的对应条件)
when matched then
update set
A.column2=B.column2,
A.column3=B.column3...
when not matched then
insert (column1,column2...)
values (B.column1,B.column2...);
以上是完整的一句SQL语句,它完成的任务是将表B的数据合并到表A中,
这个SQL包含了2种情况的处理:
1.表B中的数据表A中已经存在时,
执行更新,定义在when matced then子句中,在update set关键字后,写要更新字段的赋值操作
2.表B中的数据表A中不存在时,
执行插入,定义在when not matched then子句中,insert后列出列名,values后是实际的字段值
判断是否已经存在的条件在on关键字后定义,一般可以使用主键进行判断,例如A.id=B.id,可以使用复杂的条件如and,or,表达式等。

merge语句是oracle提供出来为数据仓库实现方便的合并数据的,这个操作在其他数据库中一般需要用条件判断语句编程,如if... then... elsif... then... end if,其中加入1句insert、1句update来实现,但在oracle中,完全可以由一条merge语句就完成了。

这条merge语句你需要适应你需要的修改,完成后,
记得把它完整的保存在一个文本文件里,保存到某个路径,比如d:\merge.txt。

**********************************
然后是批处理文件,其中要在命令行调用SQLPLUS程序,来执行以上那条SQL,如下:
ECHO ON
@ECHO BEGIN TO MERGE TABLE A B!
SQLPLUS USER/PASSWORD@ORCL_SID
@D:\merge.sql
COMMIT
EXIT
@ECHO MERGE DATA FINISHED
PAUSE

每句话的意思是:
ECHO ON 打开输出开关
@ECHO BEGIN TO MERGE TABLE A B! @ECHO后面跟的字符是要打印在命令行里的内容,这句话执行后,命令行 会打印出BEGIN TO MERGE TABLE A B!起提示作用而已。
SQLPLUS USER/PASSWORD@ORCL_SID 在命令行里调用SQLPLUS连接oracle的命令,USER是用户名,PASSWORD是 密码,ORCL_SID是连接字符串,成功执行这条语句后,便已经从DOS转入SQLPLUS环境下了。
@D:\merge.sql SQLPLUS中调用SQL脚本的方法,就是@符号跟脚本路径就行了。
COMMIT merge操作执行后必须提交才能写入数据库。
EXIT 退出SQLPLUS环境,执行后命令行回到DOS环境下。
@ECHO MERGE DATA FINISHED 起提示作用,表明以上操作已执行完毕未出错。
PAUSE 让命令行程序执行完后不会自动关闭,而是显示“按任意键继续。。。”提示,只是给你时间看下执 行过程有无出错提示。

把上面这段脚本保存成一个bat类型文件,如merge_ab.bat,便可以执行了。

**********************************
如果你使用的是oracle,以上方法100%可以解决你的问题,如果是其他数据库,可以参考以上方法,思路是一样的,只是换一种方式实现而已。

‘叁’ 如何替换merge into

merge into 可以写insert 还有update语句来替换,具体段清语法可以根据具体业务弯掘需求查阅sql语法手册来写,很高兴为你解握闹前答,如有不解请追问。

‘肆’ (急)MERGE INTO 问题

排错方法:
1.单独执行select B.m from B UNION ALL select C.m from C
看是否有结果,如果有结果的话,那么 on条件有虚信问题,如果没有结果,请检查你的语句结果集
2.其他差卜轮的从语法上面来看没有什么弊数错误。

请楼主再确认

‘伍’ SQL2008中Merge的用法

create table #ttt(id int,name nvarchar(10));
merge into #ttt t
using (select 1 as id ,'eee' as name ) b
on (t.id = b.id)
when matched then
update set t.name = b.name
when not matched then
insert(id,name) values(b.id,b.name);

‘陆’ 同一数据库MERGE INTO去重插入数据。

sqlserver表结构:

sql语法:

''仿友'sql_str= u"MERGE INTO T_AGENT_PHONE_DETAIL_ a " \

u"USING (select '%s' as S_TEL, '%s' as S_MOBILE) b " \

u"ON (a.S_TEL = b.S_TEL and  a.S_MOBILE = b.S_MOBILE) " \

u"WHEN NOT MATCHED THEN " \段大孝

u"INSERT " \

u"(I_CITY_ID, S_CITY_NAME, D_IN_TIME, S_DETAIL_URL ," \

u"S_MOBILE ,S_TEL ," \

u"S_COMPANY_NAME, S_CONTACT, I_SITE_ID, S_SITE_NAME, D_COMPANY_CREATE_TIME, I_DATA_TYPE, S_COMPANY_STATUS, S_COMPANY_DESC) VALUES " \

u"(%s, '%s',getdate(),'%s','%s','%s','%s','%s', '%s', '%s', '%s' , '握稿%s', '%s', '%s');" % (

              tel,

mobile,

city_id,

city_name,

detail_url,

mobile,

tel,

company_name,

contact,

self.web_id,

self.web_name,

company_create_time,

data_type,

company_status,

company_desc

)'''

不支持macdown贴上图片方便观看:

‘柒’ 列举一些sql高级查询语句

1.集合操作
学习oracle中集合操作的有关语句,掌握union,union all,minus,interest的使用,能够描述结合运算,并且能够将多个查询组合到一个查询中去,能够控制行返回的顺序。
包含集合运算的查询称为复合查询。见表格1-1
表1-1
Operator Returns content
UNION 由每个查询选择的所有不重复的行 并集不包含重复值
UNION ALL 由每个查询选择的所有的行,包括所有重复的行 完全并集包含重复值
INTERSECT 由每个查询选择的所有不重复的相交行 交集
MINUS 在第一个查询中,不在后面查询中,并且结果行不重复 差集

所有的集合运算与等号的优先级相同,如果SQL语句包含多个集合运算并且没有圆括号明确地指定另一个顺序,Oracle服务器将以从左到右的顺序计算。你应该使用圆括号来明确地指定带另外的集合运算的INTERSECT (相交) 运算查询中的赋值顺序。
Union all 效率一般比union高。
1.1.union和union all
UNION(联合)运算
UNION运算返回所有由任一查询选择的行。用UNION运算从多表返回所有行,但除去任何重复的行。
原则 :

􀂃?被选择的列数和列的数据类型必须是与所有用在查询中的SELECT语句一致。列的名字不必相同。
􀂃?联合运算在所有被选择的列上进行。
􀂃?在做重复检查的时候不忽略空(NULL)值。
􀂃?IN运算有比UNION运算高的优先级。
􀂃?在默认情况下,输出以SELECT子句的第一列的升序排序。

全联合(UNION ALL)运算
用全联合运算从多个查询中返回所有行。
原则

􀂃?和联合不同,重复的行不被过滤,并且默认情况下输出不排序。
􀂃?不能使用DISTINCT关键字。
使用:
Select statement union | union all Select statement;

1.2.intersect交集操作
相交运算
用相交运算返回多个查询中所有的公共行。 无重复行。
原则

􀂃?在查询中被 SELECT 语句选择的列数和数据类型必须与在查询中所使用的所有的 SELTCT 语句中的一样,但列的名字不必一样。
􀂃?相交的表的倒序排序不改变结果。
􀂃?相交不忽略空值。
使用:
Select statement intersect all Select statement;

1.3. minus差集操作
相减运算
用相减运算返回由第一个查询返回的行,那些行不出现在第二个查询中 (第一个SELECT语句减第二个SELECT语句)。
原则

􀂃?在查询中被SELECT语句选择的列数和数据类型必须与在查询中所使用的所有的SELTCT语句中的一样,但列的名字不必一样。
􀂃?对于MINUS运算,在WHERE子句中所有的列都必须在SELECT子句中。

集合运算的原则
?在两个SELECT列表中的表达式必须在数目上和数据类型上相匹配
?可以用圆括号改变执行的顺序
?ORDER BY子句:–只能出现在语句的最后–从第一个SELECT语句接收列名、别名,或者位置记号

注:?除了UNION ALL,重复行自动被清除
?在结果中的列名是第一个查询中出现的列名
?除了UNION ALL,默认情况下按升序顺序输出
2.exists和not exists的使用
2.1. exists的使用
Exists用于只能用于子查询,可以替代in,若匹配到结果,则退出内部查询,并将条件标志为true,传回全部结果资料,in不管匹配到匹配不到都全部匹配完毕,使用exists可以将子查询结果定为常量,不影响查询效果,而且效率高。如查询所有销售部门员工的姓名,对比如下:
IN is often better if the results of the subquery are very small
When you write a query using the IN clause, you're telling the rule-based optimizer that you want the inner query to drive the outer query.
When you write EXISTS in a where clause, you're telling the optimizer that you want the outer query to be run first, using each value to fetch a value from the inner query.
In many cases, EXISTS is better because it requires you to specify a join condition, which can invoke an INDEX scan. However, IN is often better if the results of the subquery are very small. You usually want to run the query that returns the smaller set of results first.

In和exists对比:
若子查询结果集比较小,优先使用in,若外层查询比子查询小,优先使用exists。因为若用in,则oracle会优先查询子查询,然后匹配外层查询,若使用exists,则oracle会优先查询外层表,然后再与内层表匹配。最优化匹配原则,拿最小记录匹配大记录。
使用in
select last_name, title
from s_emp
where dept_id in
(select id
from s_dept
where name='Sales');

使用exists
select last_name,title
from s_emp e
where exists
(select 'x' --把查询结果定为constant,提高效率
from s_dept s where s.id=e.dept_id and s.name='Sales');
2.2 not exists的使用
与exists 含义相反,也在子查询中使用,用于替代not in。其他一样。如查询不在销售部的员工姓名
select last_name,title
from s_emp e
where not exists
(select 'x' --把查询结果定为constant,提高效率
from s_dept s where s.id=e.dept_id and s.name='Sales');
3.with子句
9i新增语法
1.使用with子句可以让子查询重用相同的with查询块,通过select调用,一般在with查询用到多次情况下。

2.with子句的返回结果存到用户的临时表空间中,只做一次查询,提高效率。

3.有多个查询的时候,第1个用with,后面的不用with,并且用逗号隔开。

5.最后一个with子句与下面的查询之间不能有逗号,只通过右括号分割,查询必须用括号括起来

6.如果定义了with子句,而在查询中不使用,那么会报ora-32035错误:未引用在with子句中定义的查询名。(至少一个with查询的name未被引用,解决方法是移除未被引用的with查询)

7.前面的with子句定义的查询在后面的with子句中可以使用。
With子句目的是为了重用查询。

语法:
With alias_name as (select1), --as和select中的括号都不能省略
alias_name2 as (select2),--后面的没有with,逗号分割

alias_namen as (select n) –与下面的查询之间没有逗号
Select ….
如查询销售部门员工的姓名:
--with clause
with a as
(select id from s_dept where name='Sales' order by id)
select last_name,title
from s_emp where dept_id in (select * from a);--使用select查询别名

使用with子句,可以在复杂的查询中预先定义好一个结果集,然后在查询中反复使用,不使用会报错。而且with子句获得的是一个临时表,如果在查询中使用,必须采用select from with查询名,比如
With cnt as(select count(*) from table)
Select cnt+1 from al;
是错误的。必须是
With cnt as(select count(*) shumu from user_tables)
Select shumu+1 from cnt;
--直接引用with子查询中的列别名。

一个with查询的实例:
查询出部门的总薪水大于所有部门平均总薪水的部门。部门表s_dept,员工表s_emp。
分析:做这个查询,首先必须计算出所有部门的总薪水,然后计算出总薪水的平均薪水,再筛选出部门的总薪水大于所有部门总薪水平均薪水的部门。那么第1步with查询查出所有部门的总薪水,第2步用with从第1步获得的结果表中查询出平均薪水,最后利用这两次的with查询比较总薪水大于平均薪水的结果,如下:
with
--step1:查询出部门名和部门的总薪水
dept_costs as(
select a.name,sum(b.salary) dept_total
from
s_dept a,s_emp b
where a.id=b.dept_id
group by a.name
),
--step2:利用上一个with查询的结果,计算部门的平均总薪水
avg_costs as(
select sum(dept_total)/count(*) dept_avg
from dept_costs
)
--step3:从两个with查询中比较并且输出查询结果
select name,dept_total
from dept_costs
where
dept_total>
(
select dept_avg
from
avg_costs
)
order by name;

从上面的查询可以看出,前面的with查询的结果可以被后面的with查询重用,并且对with查询的结果列支持别名的使用,在最终查询中必须要引用所有with查询,否则会报错ora-32035错误。

再如有这样一个需求:一个查询,如果查询的结果行不满足是10的倍数,则补空行,直到是查询出的行数是10的倍数。例如:select * from trademark这个查询。
with cnt as (select 10-mod(count(*),10) shumu from trademark) –查询比10的倍数差几个空行
select id,name
from trademark
union all --空行加进去
select null,null --补空行
from al connect by rownum<=(select shumu from cnt); --10个中connect by可以使用子查询
10g之前的写法
with cnt as (select 10-mod(count(*),10) shumu from trademark) –查询比10的倍数差几个空行
select id,name
from trademark
union all --空行加进去
select null,null --补空行
from all_objects where rownum<=(select shumu from cnt);--使用all_objects行比较多

4.merge into合并资料
语法:(其中as可以省略)
MERGE INTO table_name AS table_alias
USING (table|view|sub_query) AS alias
ON (join condition)
WHEN MATCHED THEN
UPDATE SET
col1 = col_val1,
col2 = col2_val
WHEN NOT MATCHED THEN
INSERT (column_list)—多个列以逗号分割 //可以不指定列
VALUES (column_values);

作用:将源数据(来源于实际的表,视图,子查询)更新或插入到指定的表中(必须实际存在),依赖于on条件,好处是避免了多个insert和update操作。Merge是一个目标性明确的操作符,不允许在一个merge语句中对相同的行insert或update操作。这个语法仅需要一次全表扫描就完成了全部工作,执行效率要高于INSERT+UPDATE。例子如下:

drop table t;
CREATE TABLE T AS SELECT ROWNUM ID, A.* from DBA_OBJECTS A;

drop table t1;
CREATE TABLE T1 AS
SELECT ROWNUM ID, OWNER, TABLE_NAME, CAST('TABLE' AS VARCHAR2(100)) OBJECT_TYPE
from DBA_TABLES;

select * from dba_objects;
select * from dba_tables;

MERGE INTO T1 USING T
ON (T.OWNER = T1.OWNER AND T.OBJECT_NAME = T1.TABLE_NAME AND T.OBJECT_TYPE = T1.OBJECT_TYPE)
WHEN MATCHED THEN UPDATE SET T1.ID = T.ID
WHEN NOT MATCHED THEN INSERT VALUES (T.ID, T.OWNER, T.OBJECT_NAME, T.OBJECT_TYPE);--insert后面不写表示插入全部列

MERGE INTO T1 USING T
ON (T.OWNER = T1.OWNER AND T.OBJECT_NAME = T1.TABLE_NAME)
WHEN MATCHED THEN UPDATE SET T1.ID = T.ID
WHEN NOT MATCHED THEN INSERT VALUES (T.ID, T.OWNER, T.OBJECT_NAME, T.OBJECT_TYPE);--常见错误,连接条件不能获得稳定的行,可以使用下面的用子查询

MERGE INTO T1
USING (SELECT OWNER, OBJECT_NAME, MAX(ID) ID from T GROUP BY OWNER, OBJECT_NAME) T
ON (T.OWNER = T1.OWNER AND T.OBJECT_NAME = T1.TABLE_NAME)
WHEN MATCHED THEN UPDATE SET T1.ID = T.ID
WHEN NOT MATCHED THEN INSERT VALUES (T.ID, T.OWNER, T.OBJECT_NAME);

SELECT ID, OWNER, OBJECT_NAME, OBJECT_TYPE from T
MINUS
SELECT * from T1;

drop table subs;
create table subs(msid number(9),
ms_type char(1),
areacode number(3)
);

drop table acct;
create table acct(msid number(9),
bill_month number(6),
areacode number(3),
fee number(8,2) default 0.00);

insert into subs values(905310001,0,531);
insert into subs values(905320001,1,532);
insert into subs values(905330001,2,533);
commit;

merge into acct a --操作的表
using subs b on (a.msid=b.msid)--使用原始数据来源的表,并且制定条件,条件必须有括号
when matched then
update set a.areacode=b.areacode--当匹配的时候,执行update操作,和直接update的语法不一样,不需要制定表名
when not matched then--当不匹配的时候,执行insert操作,也不需要制定表名,若指定字段插入,则在insert后用括号标明,不指定是全部插入
insert(msid,bill_month,areacode) values(b.msid,'200702',b.areacode);

另外,MERGE语句的UPDATE不能修改用于连接的列,否则会报错
select * from acct;
select * from subs;
--10g新特性,单个操作
merge into acct a
using subs b on(a.msid=b.msid)
when not matched then--只有单个not matched的时候,只做插入,不做更新,只有单个matched的时候,只做更新操作
insert(a.msid,a.bill_month,a.areacode) values(b.msid,'200702',b.areacode);

update acct set areacode=800 where msid=905320001;

delete from acct where areacode=533 or areacode=531;

insert into acct values(905320001,'200702',800,0.00);

--删除重复行
delete from subs b where b.rowid<(
select max(a.rowid) from subs a where a.msid=b.msid and a.ms_type=b.ms_type and a.areacode=b.areacode);

--10g新特性,merge操作之后,只有匹配的update操作才可以,用delete where子句删除目标表中满足条件的行。
merge into acct a
using subs b on (a.msid=b.msid)
when MATCHED then
update set a.areacode=b.areacode
delete where (b.ms_type!=0)
when NOT MATCHED then
insert(msid,bill_month,areacode)
values(b.msid,'200702',b.areacode)
where b.ms_type=0;
--10g新特性,满足条件的插入和更新
merge into acct a
using subs b on (a.msid=b.msid)
when MATCHED then
update set a.areacode=b.areacode
where b.ms_type=0
when NOT MATCHED then
insert(msid,bill_month,areacode)
values(b.msid,'200702',b.areacode)
where b.ms_type=0;

select * from subs where ms_type=0;

‘捌’ Mysql中有类似merge into的函数吗

1、在 SQL Server 中,int 数据类型是主要的整数数据类型。 在数据类型优先次序表中,bigint 位于 smallmoney 和 int 之间。

2、只有当参数表达式是 bigint 数据类型时,函数才返回 bigint。SQL Server 。不会自动将其它整数数据类型(tinyint、smallint 和 int)提升为 bigint。

3、int(M) 在 integer 数据类型中,M 表示最大显示宽度。在 int(M) 中,M 的值跟 int(M) 所占多少存储空间并无任何关系。和数字位数也无关系 int(3)、int(4)、int(8) ,在磁盘上都是占用 4 btyes 的存储空间。

4、MySQL 软件采用了双授权政策(本词条"授权政策"),它分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型网站的开发都选择 MySQL 作为网站数据库。

5、Index Key :MySQL是用来确定扫描的数据范围,实际就是可以利用到的MySQL索引部分,体现在Key Length。

6、Index Filter:MySQL用来确定哪些数据是可以用索引去过滤,在启用ICP后,可以用上索引的部分。

7、Table Filter:MySQL无法用索引过滤,回表取回行数据后,到server层进行数据过滤。

‘玖’ oracle 中 merge into 在动态sql 中怎么用

merge into table1 t
using (select a,b,c from table2)a
on (t.a=a.a and t.b=a.b)
when matched then
update set t.c=a.c
纯手打 ,望采纳