ORCALE中的 MERGE INTO UPDATE、INSERT实践

1、看到一段代码如下:

JPA与MyBatis混用;

大致的逻辑是:在异步里,计算当前时间与上一状态记录的TimeStamp创建时间的时间差(转分钟,保留毫秒数)作为上一状态的持续时间。并记录当前状态。

 

@Async
@Override
public void logAgentStatus(AgentStatus status){
    
    Integer queryStatus = CommonUtils.getQueryStatusForUserAction(status.getStatus());

    UserAction userAction = userActionRepository.finTopByUserIdAndStatusAndActionAndNewValueIsNullOrderByCreateDateDesc(status.getUserId(),queryStatus,status.getUserAction().name());

    if(!Objects.isNull(userAction) && StringUtils.isEmpty(userAction.getNewValue())){

        Double begin = new Double(userAction.getCreatedDate() != null ? userAction.getCreatedDate().getTime():System.currentTimeMillis());

        Double end = new Double(System.currentTimeMillis());

        Double min = (end - beign)/60/1000.0;

        userActionMapper.updateNewValue(Double.toString(min),userAction.getId());
    }

    UserAction userActionAvailable = userActionRepository.finTopByUserIdAndStatusAndActionAndNewValueIsNullOrderByCreateDateDesc(status.getUserId(),status.getStatus,statys.GetUserAction().name());

    if(Objects.isNull(userActionAvailable)){
        
        userActionRepository.saveAndFlush(UserAction.Builder().userId(status.getUserId())
        .action(status.getUserAction().name()).status(status.getStatus()).build());
    }

}

2、ORACLE通过查询更新表中数据

ORCALE日期、时间的处理,转:https://www.cnblogs.com/hijushen/p/4223557.html

转:https://blog.csdn.net/iteye_14659/article/details/82331422

使用一条sql代替上面的查询和更新代码,执行逻辑 :计算当前时间与上一状态记录的TimeStamp创建时间的时间差(转分钟,保留毫秒数)作为上一状态的持续时间

MERGE INTO IM_USER_ACTION_LOG A
USING(  SELECT ID,
            EXTRACT(DAY FROM (SYSTIMESTAMP - CREATED_DATE))*24*60*60 +
            EXTRACT(HOUR FROM (SYSTIMESTAMP - CREATED_DATE))*60*60 +
            EXTRACT(MINUTE FROM (SYSTIMESTAMP - CREATED_DATE)) +
            EXTRACT(SECOND FROM (SYSTIMESTAMP - CREATED_DATE))/60 AS MIN
        FROM (SELECT T.ID,T.CREATED_DATE
                FROM IM_USER_ACTION_LOG T
                WHERE   T.USER_ID = 'AA'
                    AND T.STATUS =  1
                    AND T.ACTION = 'ACTION'
                    AND T.NEW_VALUE IS NULL
                ORDER BY T.CREATED_DATE DESC)
        WHERE ROWNUM = 1) B
ON (A.ID = B.ID)
WHEN MATCHED THEN
    UPDATE SET A.NEW_VALUE = B.MIN ;     

3、自测时,发现新问题:当持续时间较短时,db字段new_value存储的数值出现类似 .14 丢失个位为0的问题,以及小数点后的位数长度太长的问题。

解决方法,转 https://blog.csdn.net/qq_34909807/article/details/76270987   

MERGE INTO IM_USER_ACTION_LOG A
USING(  SELECT ID,
            EXTRACT(DAY FROM (SYSTIMESTAMP - CREATED_DATE))*24*60*60 +
            EXTRACT(HOUR FROM (SYSTIMESTAMP - CREATED_DATE))*60*60 +
            EXTRACT(MINUTE FROM (SYSTIMESTAMP - CREATED_DATE)) +
            EXTRACT(SECOND FROM (SYSTIMESTAMP - CREATED_DATE))/60 AS MIN
        FROM (SELECT T.ID,T.CREATED_DATE
                FROM IM_USER_ACTION_LOG T
                WHERE   T.USER_ID = 'AA'
                    AND T.STATUS =  1
                    AND T.ACTION = 'ACTION'
                    AND T.NEW_VALUE IS NULL
                ORDER BY T.CREATED_DATE DESC)
        WHERE ROWNUM = 1) B
ON (A.ID = B.ID)
WHEN MATCHED THEN
    UPDATE SET A.NEW_VALUE = TO_CHAR(B.MIN,'fm9999990.9999999999') ;     

4、为避免重复插入当前状态的记录,所以JAVA代码中的逻辑是先查询,查询不到再插入新的值。此处不能使用 MERGE INTO(它是使用USING中的数据按WHERE MATCHED 或者 NOT MATCHED 执行THEN的逻辑)。

尝试 (这种一般用在表复制场景)INSERT INTO TB(...) SELECT ...FROM TB WHERE NOT EXISTS(SELECT ... FROM TB WHERE ) 转 https://blog.csdn.net/sun5769675/article/details/50158531?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

但是很不幸,NOT EXISTS子句判断条件没有唯一性,会导致插入多条。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值