Mysql创建自增&循环序列(函数实现循环,取next)

Mysql创建自增&循环序列(函数实现循环,取next)

前言

这篇文章是很早之前写的了,现在回过头来看,当时只是想获取主键id。现在都不用这种方式了(mybatis-plus提供 IdWord.getId(),不止这一种方式)。
ps:一般来说,java尽量避免使用函数和存储过程。不流行了是一个原因,最重要的是不好调试和移植。

1:oracle可以直接创建自增循环序列,但是mysql没有序列
2:mysql实现序列的方式:创建序列表(最少要有序列名,序列值、自增值),基于表创建function实现序列功能
3:序列可以干啥–(日期+时间+序列)可以当做业务流水号,唯一标识。

table

创建表的sql,其中min_value和max_value可以去掉
这里创建的是7位自增循环序列,为了简单value直接从1000000(7位)开始。

CREATE TABLE `t_sequence` (
  `id` bigint(21) NOT NULL COMMENT '序列号ID',
  `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '序列名',
  `value` bigint(21) NOT NULL COMMENT '序列值',
  `increment` int(1) NOT NULL DEFAULT 1 COMMENT '序列自增值 1',
  `min_value` bigint(21) NOT NULL DEFAULT 1000000 COMMENT '最小序列值',
  `max_value` bigint(21) NOT NULL DEFAULT 9999999 COMMENT '最大序列值',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `id` (`id`) USING BTREE,
  UNIQUE KEY `name` (`name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin comment '序列表';

function

先创建一个获取序列当前value的函数

CREATE FUNCTION get_seq_current(seq_name char(100))
	RETURNS BIGINT
	LANGUAGE SQL
	DETERMINISTIC
	CONTAINS SQL
	SQL	SECURITY DEFINER
	COMMENT ''
BEGIN
	DECLARE current_value BIGINT;
	SET current_value = 0;
	SELECT value into current_value FROM t_sequence WHERE name = seq_name;
	RETURN current_value;
END;

在创建一个获取序列最大值的函数`

##获取最大value
CREATE FUNCTION get_seq_max(seq_name char(100))
	RETURNS BIGINT
	LANGUAGE SQL
	DETERMINISTIC
	CONTAINS SQL
	SQL	SECURITY DEFINER
	COMMENT ''
BEGIN
	DECLARE max BIGINT;
	SET max = 0;
	SELECT max_value into max FROM t_sequence WHERE name = seq_name;
	RETURN max;
END;

最后创建一个获取序列下一个值的函数(在该函数内实现自增以及循环)

CREATE FUNCTION get_seq_next1(seq_name char(100))
	RETURNS BIGINT
	LANGUAGE SQL
	DETERMINISTIC
	CONTAINS SQL
	SQL	SECURITY DEFINER
	COMMENT ''
BEGIN
	IF(get_seq_current(seq_name) >= get_seq_max(seq_name))THEN
		update t_sequence SET value = min_value where name = seq_name;
	ELSE
		update t_sequence SET value = (value + increment) where name = seq_name;
	END IF;
	RETURN get_seq_current(seq_name);
END;

效果

当前的数据,序列名:base_number,当前值:9999999
这个是我当前的数据
使用函数获取当前的value,得到结果:9999999
在这里插入图片描述
使用函数获取下一个value,得到结果:1000000
在这里插入图片描述

在Django中,如果你想让MySQL数据库中的表字段自增并且包含字母,通常我们不会直接创建一个混合了数字和字母的自增ID。因为默认的自增字段(如`AutoField`)仅支持数字类型。但是你可以通过一些策略间接实现类似功能: 1. **使用字符串序列**:可以创建一个单独的模型字段(比如`CharField`),存储按字母排序的数字序列。例如,`A01`, `A02`, ...。然后,在应用业务规则生成新的序列号。 ```python from django.db import models class AlphabeticalSequence(models.Model): sequence = models.CharField(max_length=4, unique=True) # 当需要新序号时 def generate_next_sequence(): # 获当前最高顺序(假设已存在'A999') max_sequence = AlphabeticalSequence.objects.order_by('-sequence').first() if max_sequence: next_number = int(max_sequence.sequence[-1]) + 1 return f"A{next_number:0>3}" else: return "A001" # 使用生成函数 new_sequence = generate_next_sequence() ``` 2. **结合数字+序列号**:如果需要更精确的控制,可以创建一个组合字段,由一个数字字段(作为自增ID)和另一个辅助字段(如`CharField`)组成。但请注意,这将增加数据库查询复杂性和维护成本。 ```python class CustomAutoNumber(models.Model): id = models.AutoField(primary_key=True) code = models.CharField(max_length=3, blank=True) # 字母前缀,初始为空 number = models.IntegerField(default=1, db_index=True) def save(self, *args, **kwargs): if not self.code: max_code = CustomAutoNumber.objects.filter(code__isnull=False).aggregate( Max('code'))['code__max'] self.code = 'A' if max_code is None else chr(ord(max_code[-1].upper()) + 1) + str(self.number) super().save(*args, **kwargs) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值