美文网首页
组合条件限制唯一记录 —— 组合唯一索引替代方案

组合条件限制唯一记录 —— 组合唯一索引替代方案

作者: Pagenny | 来源:发表于2018-10-12 17:02 被阅读0次
    场景:

    同一个问题,每个用户只能有一个回答

    解决方案1:

    回答问题(新增回答记录)之前,根据 问题ID 和 用户ID 查询用户是否已经回答指定问题,如果已经有回答则提示用户不能重复回答。

    分析:如果前端同时发起多个一模一样的请求(不能相信前端的任何操作),那么数据还是会重复插入。先查后插入的思路在并发下总会存在这样的问题。pass 掉!

    解决方案2:

    数据库表建立 问题ID 和 用户ID 的组合唯一索引,在程序中捕获 DuplicateKeyException 异常,如果捕获到该异常,则为唯一键冲突,提示用户不能重复回答(当然,也得保证不是由其它唯一索引引起的异常)

    分析:该方法在能确保在数据库中数据的唯一性,一般足够了。但是在本次场景中,删除是逻辑位标记删除,也就是说其实表中还是会操作同样的 问题ID 和 用户ID 有多条数据的结果,只不过有效的(没有标记为删除的)结果只有一条,这个时候用唯一索引就不适合了,只能寻求其它方法。

    解决方案3:

    使用 not exists 条件语句。根据语句执行的返回值判断是否成功。如果返回值为 0,说明没有执行插入操作,即数据库中已经有了重复的数据。
    不要忘记限制条数为1 ( 后面的 limit 1 ),否则还是会插入多条重复的数据。

    insert into t_answer (ID, QUESTION_ID, CREATE_USER_ID, CREATE_TIME)
        select
            #{id,jdbcType=VARCHAR}, #{questionId,jdbcType=VARCHAR},
            #{createUserId,jdbcType=VARCHAR}, #{createTime,jdbcType=TIMESTAMP}
        from dual where not exists
        (
            select id from t_answer where 
            create_user_id = #{createUserId,jdbcType=VARCHAR}
            and question_id = #{questionId,jdbcType=VARCHAR}
            and DELETE_TAG = 0
        ) limit 1
    

    以上是在 mybaties 中的用法,作为参考,实际使用中也可以自己去拼接。其中 DELETE_TAG 即为删除标识,为 0 表示有效数据,为 1 表示已删除数据。

    相关文章

      网友评论

          本文标题:组合条件限制唯一记录 —— 组合唯一索引替代方案

          本文链接:https://www.haomeiwen.com/subject/nsugaftx.html