关于ORACLE merge into 的两个常见错误

------- MERGE语法简介 语法如下: MERGE hint INTO schema . table t_alias USING schema . { table | view | subquery } t_alias ON (condition) WHEN MATCHED THEN merge_update_clause WHEN NOT MATCHED THEN merge_insert_clause;

--好处:是执行 同时有插入和更新操作时效率最高的脚本 讲解前建表:

CREATE TABLE TEST_111111  (ID NUMBER(18),  NAME VARCHAR2(255)  );  INSERT INTO TEST_111111  VALUES (1,'小红');  INSERT INTO TEST_111111  VALUES (2,'小红');  CREATE TABLE TEST_222222  AS  SELECT * FROM TEST_111111  WHERE ID = 1;

  Oracle10g中MERGE的完善 在Oracle10g以后,Oracle的MERGE发生了改变  UPDATE和INSERT动作可只出现其一  --可以只出现update   MERGE INTO TEST_111111 T1  USING TEST_222222 T2  ON (T1.ID = T2.ID)  WHEN MATCHED THEN    UPDATE SET T1.NAME = T2.NAME; --也可选择仅仅INSERT目标表而不做任何UPDATE动作  MERGE INTO TEST_111111 T1  USING TEST_222222 T2  ON (T1.ID = T2.ID)  WHEN NOT MATCHED THEN    INSERT VALUES (T2.ID, T2.NAME);  --而9i 版本的 则update 与 insert  都必须存在  MERGE INTO TEST_111111 T1  USING TEST_222222 T2  ON (T1.ID = T2.ID)  WHEN MATCHED THEN    UPDATE SET T1.NAME = T2.NAME  WHEN NOT MATCHED THEN    INSERT VALUES (T2.ID, T2.NAME);

-----------两种最常见的错误:

-PART1.ora-30926 :无法在源表中获得一组稳定的行

INSERT INTO TEST_111111  VALUES (1,'小红');

上面这条语句执行两次,插入两条相同的记录

INSERT INTO TEST_222222   SELECT * FROM TEST_111111  WHERE ID = 1;

MERGE INTO TEST_111111 T1  USING TEST_222222 T2 ON (T1.NAME = T2.NAME )  WHEN MATCHED THEN  UPDATE SET T1.ID = 521  WHEN NOT MATCHED THEN  INSERT VALUES (T2.ID,T2.NAME);

这时候就会报ORA-30926:无法再源表中获得一组稳定的行

原因 :T1 表为源表,意思是 在 ON(CONDITION) 这里在做CONDITION 判断的时候,匹配到的T1中的数据不止一条,所以CONDITION 这里建议 以主键为条件,这样就避免了匹配到多条数据的问题。

解决方案:知道了出错原因,解决起来就有方向可寻

假设 iD为主键,脚本改成

MERGE INTO TEST_111111 T1  USING TEST_222222 T2  ON (T1.ID= T2.ID)  WHEN MATCHED THEN  UPDATE SET T1.NAME = T2.NAME  WHEN NOT MATCHED THEN  INSERT VALUES (T2.ID,T2.NAME);

--PART2:ora-38104:无法更新on子句中引用的列

 MERGE INTO TEST_111111 T1  USING TEST_222222 T2  ON (T1.NAME = T2.NAME )  WHEN MATCHED THEN  UPDATE SET T1.NAME = T2.NAME  WHEN NOT MATCHED THEN  INSERT VALUES (T2.ID,T2.NAME);

出错原因:这里在 做ON 判断时 已经对name 字段进行匹配了,这就好比我在进行一组表更新操作的时候的锁表状态,所以想更新NAME 便不能用NAME 做条件判断。

思考:错误二引发对错误一的思考

假使我在做ON判断的时候用的是表的主键,然后我想做UPDATE 操作的时候如果是on 里面的条件字段,也就是说 要更新的是  数据库 中 表的主键 ,这也就违背了  数据库的主键约束条件。因此,从错误二去反推错误一,就自然好理解了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏DT乱“码”

Oracle CASE WHEN的一些使用

1. CASE WHEN 表达式有两种形式 复制代码代码如下: --简单Case函数   CASE sex   WHEN '1' THEN '男'   ...

1955
来自专栏Samego开发资源

入门级Oracle存储过程 | oracle

902
来自专栏沃趣科技

innodb存储引擎锁的实现

通常,我们在95%以上的MySQL使用场景中,从一定程度上来讲,就是在使用InnoDB存储引擎,很多时候我们选择使用InnoDB存储引擎的原因,就是因为它支持高...

1005
来自专栏测试开发架构之路

MySQL实现全关联 full outer join

SQL LEFT JOIN 关键字 LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中...

2643
来自专栏calmound

操作数据表

打开数据库    use 数据库 ---- use mydata 查看数据库    show databases 显示当前用户打开的数据库   SELECT ...

3066
来自专栏云霄雨霁

数据更新语言DML

1300
来自专栏Hadoop数据仓库

Oracle中的三种 UPDATE FROM 的解决方案

表的更新操作中,在很多情况下需要在表达式中引用要更新的表以外的数据。象sql server提供了update的from 子句,可以将要更新的表与其它的数据源连接...

1919
来自专栏WindCoder

MySQL中INSERT INTO SELECT的应用

这种方法常用在目标表已经存在数据库中.需要从源表把数据插入到目标表的情况.如果目标表和源表的列相同,就不必列出数据列了.(未完待续,另参考资料中重复项太多,暂且...

481
来自专栏一个会写诗的程序员的博客

SELECT 语句中的 子查询(Sub Query)

子查询(Sub Query)或者说内查询(Inner Query),也可以称作嵌套查询(Nested Query),是一种嵌套在其他 SQL 查询的 WHERE...

652
来自专栏PHP技术

mysql中case when用法

mysql中case when语句的使用方法: mysql中也有像php语言中switch case 这样的语句。 例如,下面的语句显示中文年月 sele...

3645

扫码关注云+社区