merge into 更新和插入

近期在进行熟悉代码和进行优化的时候,遇到了业务员提出的一个问题,报的错误。

### Error updating database Cause: java.sql.sQLException: ORA-38104: Columns referenced in the ON Clause cannot be updated: "A"."SCHEME_ID" ### The error may exst in file (../mapper/ImplPersonItemMapper.xm] 
### The error may involve defaultParameterMap ### The error occurred while setting parameters ### SQL: 

MERGE INTO SCHEME_IMPL_PERSON_ITEM A USING 
	(SELECT * FROM SCHEME_IMPL_PERSON_ITEM WHERE SCHEME_ID = ?  AND USER_CODE = ? AND TARGET_ID = ? ) b
	ON A.SCHEME_ID = b.SCHEME_ID AND A.USER_CODE = b.USER_CODE AND A.TARGET_ID = B.TARGET_ID 
	WHEN MATCHED THEN  
        UPDATE SET SCHEME_ID = ?, USER_NAME = ?, USER_ID = ? 
        WHERE SCHEME_ID = ? AND USER_CODE = ? AND TARGET_ID = ? 
	WHEN NOT MATCHED THEN 
		INSERT (DEPT_ID,USER_ID,USER_NAME) VALUES (?,?,?)

### Cause: java.sq.sQLException: ORA-38104: Columns referenced in the ON Clause cannot be updated: "A"."SCHEME_ID" , uncategorized sQLException; SQL state [99999]: error code [38104] ORA-38104:
Columns referenced in the ON Clause cannot be updated: "A".""SCHEME_ID"; nested exception is java.sgl.SQLException:ORA-38104: Columns referenced in the ON Clause cannot be updated: "A"."SCHEME_ID"

:因为需要保密,不能过多的完全粘贴全部错误信息,但是去掉的也是部分字段,不影响目前问题的叙述。

1、介绍一下 Oracle ORA-38104 错误。

最开始我没有弄清楚这个错误是什么意思,所以就去百度搜索。首先按搜索了 SQL state [99999]。后来又去搜索了一下 ORA-38104 是什么意思。百度得到的解释是:Oracle ORA-38104:ON 子语句中引用的列不能更新。

什么是 ORA-38104 错误?

ORA-38104 是 Oracle 数据库中的一个错误代码,它表示在 update 语句中引用了 on 子句中的列,而这些列是不能被更新的。当我们尝试更新这些列时,Oracle 就会报 ORA-38104 错误。

上面是我在百度上面搜索到的,当然我自己肯定没能解释详细,有兴趣的可以搜索一下。

上面的解释给我的理解就是:

在上面错误的 sql 当中,on 后面出现的字段是不能出现在 update 语句里面的。


2、介绍一下 merge into 语句。

merge into ,简单来说就是判断表中有没有符合 on() 条件中的数据,有了就更新数据,没有就插入数据。

:我是使用了错误的语句当中“?”,真实当中需要传入的 mapper 当中的变量值

2.1 当只有 update 的时候。

merge into SCHEME_IMPL_PERSON_ITEM A using
	(SELECT * FROM SCHEME_IMPL_PERSON_ITEM WHERE SCHEME_ID = ?  AND USER_CODE = ? AND TARGET_ID = ? ) B
   on (A.SCHEME_ID = b.SCHEME_ID AND A.USER_CODE = b.USER_CODE AND A.TARGET_ID = B.TARGET_ID)
   WHEN MATCHED THEN  
     UPDATE SET SCHEME_ID = ?, USER_NAME = ?, USER_ID = ? 
     WHERE SCHEME_ID = ? AND USER_CODE = ? AND TARGET_ID = ? 

此时上面的语句当中是只有 update 的,且 on 的条件后面是有 update 需要更改的字段。所以可以把在 on 里面需要的条件放到 update 的子句 where 后面。

merge into SCHEME_IMPL_PERSON_ITEM A using
	(SELECT * FROM SCHEME_IMPL_PERSON_ITEM WHERE SCHEME_ID = ?  AND USER_CODE = ? AND TARGET_ID = ? ) B
   on (A.USER_CODE = b.USER_CODE AND A.TARGET_ID = B.TARGET_ID)
   WHEN MATCHED THEN  
     UPDATE SET SCHEME_ID = ?, USER_NAME = ?, USER_ID = ? 
     WHERE SCHEME_ID = ? AND USER_CODE = ? AND TARGET_ID = ? AND A.SCHEME_ID = b.SCHEME_ID

这样是能够完成更新的。

2.2 当语句里面有 insert 的时候

merge into SCHEME_IMPL_PERSON_ITEM A using
	(SELECT * FROM SCHEME_IMPL_PERSON_ITEM WHERE SCHEME_ID = ?  AND USER_CODE = ? AND TARGET_ID = ? ) B
   on (A.SCHEME_ID = b.SCHEME_ID AND A.USER_CODE = b.USER_CODE AND A.TARGET_ID = B.TARGET_ID)
   WHEN MATCHED THEN  
     UPDATE SET SCHEME_ID = ?, USER_NAME = ?, USER_ID = ? 
     WHERE SCHEME_ID = ? AND USER_CODE = ? AND TARGET_ID = ?
   WHEN NOT MATCHED THEN 
		INSERT (DEPT_ID,USER_ID,USER_NAME) VALUES (?,?,?)

这个时候是属于更新或插入同一张表里面,再次使用上面的方法的时候就不会成功了所以需要稍稍更改一下 sql

merge into SCHEME_IMPL_PERSON_ITEM A using
	(SELECT ? SCHEME_ID, ? USER_CODE, ? USER_CODE FROM dual) B
   on (A.SCHEME_ID = b.SCHEME_ID AND A.USER_CODE = b.USER_CODE AND A.TARGET_ID = B.TARGET_ID)
   WHEN MATCHED THEN  
     UPDATE SET USER_NAME = ?, USER_ID = ? 
     WHERE SCHEME_ID = ? AND USER_CODE = ? AND TARGET_ID = ?
   WHEN NOT MATCHED THEN 
		INSERT (DEPT_ID,USER_ID,USER_NAME) VALUES (?,?,?)

这样的话,就可以实现有则更新,无则新增的需求。

以上只是属于我这个初学者的一些记录,能够解决掉您的问题更好,属于个人纪录日常问题!!!

你可能感兴趣的:(数据库,oracle)