MySQL中获取一个或多个序列

Posted 上善若水

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL中获取一个或多个序列相关的知识,希望对你有一定的参考价值。

一、前言

项目应用中,曾有以下一个场景:
接口中要求发送一个int类型的流水号,由于多线程模式,如果用时间戳,可能会有重复的情况(当然概率很小)。
所以想到了利用一个独立的自增的sequence来解决该问题。
当前数据库为:mysql
由于mysql和oracle不太一样,不支持直接的sequence,所以需要创建一张table来模拟sequence的功能,

二、SQL脚本

-- 创建 t_sequence 序列表
DROP TABLE IF EXISTS t_sequence; 
CREATE TABLE t_sequence ( 
     name VARCHAR(50) NOT NULL COMMENT '序列名',
     current_value INT NOT NULL COMMENT '当前值', 
     increment INT NOT NULL DEFAULT 1 COMMENT '自增幅度', 
     PRIMARY KEY (name) 
) ENGINE=InnoDB COMMENT '序列表'; 

-- 创建函数:获取当前值
DROP FUNCTION IF EXISTS seq_currval; 
DELIMITER $ 
CREATE FUNCTION seq_currval (seq_name VARCHAR(50)) 
     RETURNS INTEGER
     LANGUAGE SQL 
     DETERMINISTIC 
     CONTAINS SQL 
     SQL SECURITY DEFINER 
     COMMENT ''
BEGIN
     DECLARE value INTEGER; 
     SET value = 0; 
     SELECT current_value INTO value 
          FROM t_sequence
          WHERE name = seq_name; 
     RETURN value; 
END
$ 
DELIMITER ; 

-- 创建函数:获取下一个值
DROP FUNCTION IF EXISTS seq_nextval; 
DELIMITER $ 
CREATE FUNCTION seq_nextval (seq_name VARCHAR(50)) 
     RETURNS INTEGER
     LANGUAGE SQL 
     DETERMINISTIC 
     CONTAINS SQL 
     SQL SECURITY DEFINER 
     COMMENT ''
BEGIN
     UPDATE t_sequence
          SET current_value = current_value + increment 
          WHERE name = seq_name; 
     RETURN seq_currval(seq_name); 
END
$ 
DELIMITER ; 

-- 创建函数:获取下多个值
DROP FUNCTION IF EXISTS seq_multival; 
DELIMITER $ 
CREATE FUNCTION seq_multival (seq_name VARCHAR(50),step int) 
     RETURNS INTEGER
     LANGUAGE SQL 
     DETERMINISTIC 
     CONTAINS SQL 
     SQL SECURITY DEFINER 
     COMMENT ''
BEGIN
     UPDATE t_sequence
          SET current_value = current_value + step 
          WHERE name = seq_name; 
     RETURN seq_currval(seq_name); 
END
$ 
DELIMITER ; 

-- 创建函数:更新当前值
DROP FUNCTION IF EXISTS seq_setval; 
DELIMITER $ 
CREATE FUNCTION seq_setval (seq_name VARCHAR(50), value INTEGER) 
     RETURNS INTEGER
     LANGUAGE SQL 
     DETERMINISTIC 
     CONTAINS SQL 
     SQL SECURITY DEFINER 
     COMMENT ''
BEGIN
     UPDATE t_sequence
          SET current_value = value 
          WHERE name = seq_name; 
     RETURN seq_currval(seq_name); 
END
$ 
DELIMITER ; 

三、通过java代码调用

接口类:

import com.deewin.aftermarket.admin.pojo.Sequence;
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * <p>
 * 序列表 服务类
 * </p>
 *
 * @author bitaotao
 * @since 2022-09-02
 */
public interface ISequenceService extends IService<Sequence> 
    /**
     * 获取下一个序列值
     * @param seqName 序列名
     * @return
     */
    Integer getNextSeqVal(String seqName);

    /**
     * 获取下多个序列值
     * @param seqName 序列名
     * @param step 步长
     * @return
     */
    Integer getMultiSeqVal(String seqName,Integer step);

    /**
     * 设置序列值
     * @param seqName 序列名
     * @param initVal 初始值
     * @return
     */
    Integer setSeqVal(String seqName,Integer initVal);

接口实现类:

import com.deewin.aftermarket.admin.pojo.Sequence;
import com.deewin.aftermarket.admin.mapper.SequenceMapper;
import com.deewin.aftermarket.admin.service.ISequenceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 序列表 服务实现类
 * </p>
 *
 * @author bitaotao
 * @since 2022-09-02
 */
@Service
public class SequenceServiceImpl extends ServiceImpl<SequenceMapper, Sequence> implements ISequenceService 

    /**
     * 获取下一个序列值
     * @param seqName 序列名
     * @return
     */
    @Override
    public Integer getNextSeqVal(String seqName) 
        Integer val = this.baseMapper.getNextSeqVal(seqName);
        return val;
    

    /**
     * 获取下多个序列值
     * @param seqName 序列名
     * @param step 步长
     * @return
     */
    @Override
    public Integer getMultiSeqVal(String seqName, Integer step) 
        Integer val = this.baseMapper.getMultiSeqVal(seqName,step);
        return val;
    

    /**
     * 设置序列值
     * @param seqName 序列名
     * @return
     */
    @Override
    public Integer setSeqVal(String seqName,Integer initVal) 
        return this.baseMapper.setSeqVal(seqName,initVal);
    

数据访问接口类

import com.deewin.aftermarket.admin.pojo.Sequence;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 * <p>
 * 序列表 Mapper 接口
 * </p>
 *
 * @author bitaotao
 * @since 2022-09-02
 */
public interface SequenceMapper extends BaseMapper<Sequence> 

    Integer getNextSeqVal(String seqName);

    Integer getMultiSeqVal(String seqName, Integer step);

    Integer setSeqVal(String seqName, Integer initVal);

mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.deewin.aftermarket.admin.mapper.SequenceMapper">

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.deewin.aftermarket.admin.pojo.Sequence">
        <id column="name" property="name" />
        <result column="current_value" property="currentValue" />
        <result column="increment" property="increment" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        `name`, current_value, `increment`
    </sql>

    <select id="getNextSeqVal" resultType="java.lang.Integer">
        SELECT seq_nextval('$seqName')
    </select>

    <select id="getMultiSeqVal" resultType="java.lang.Integer">
        SELECT seq_multival('$seqName',#step)
    </select>

    <select id="setSeqVal" resultType="java.lang.Integer">
        SELECT seq_setval('$seqName',#initVal)
    </select>
</mapper>

以上是关于MySQL中获取一个或多个序列的主要内容,如果未能解决你的问题,请参考以下文章

MySQL中获取一个或多个序列

mysql 创建[序列],功能类似于oracle的序列

mysql 创建[序列],功能类似于oracle的序列

怎么重置mysql的自增列AUTO

MySQL (Laravel Eloquent) - 当两列同时有两个或多个值时获取记录

如何使用会话ID从php mysql中的两个或多个表中获取值