MySQL ID 自定义函数全自动生成 newid

1、本文适用MySQL8.0以上,其它版本未测试,开发人员无测试环境,建议使用DOCKER,一行命令即实现安装测试.

注意:以下命令创建的MYSQL数据库

  • 端口:3306
  • 账号:root
  • 密码:xxxx@PasswOrdD8mi
docker run --name mysql -p 3306:3306 -v /light/mysql/conf:/etc/mysql/conf.d -v /light/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=xxxx@PasswOrdD8mi -e TZ=Asia/Shanghai -d mysql --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --lower_case_table_names=1 --log_bin_trust_function_creators=true

2、现状:MySQL有内置的UUID()或者UUID_SHORT()可以满足到大多数场景,但当我们看到如下所示ID时候,维护是非常不便

MySQL ID 自定义函数全自动生成 newid_第1张图片

3、为得到更有“意义”的ID,或者说表意ID,或者叫顺序号ID,我们要自己生成,如下图所示:

 MySQL ID 自定义函数全自动生成 newid_第2张图片

4、MYSQL自定义函数,实现自增ID

使用时直接输入ID分组即可自动增加,不需要手工配置,NEWID函数参数根据需要自己填写即可,非常方便,用法如下:

select newid(null), newid('USER'), newid('EQUIP');

 5、先生成ID数据表

MySQL ID 自定义函数全自动生成 newid_第3张图片

生成脚本

drop table if exists t_sm_id;

/*==============================================================*/
/* Table: t_sm_id                                               */
/*==============================================================*/
create table t_sm_id
(
   id                   varchar(50) not null comment 'rowid',
   syscode              varchar(20) comment '功能编码',
   last_id              bigint comment '最新id',
   remark               varchar(200) comment '备注',
   create_time          varchar(30),
   update_time          varchar(30),
   create_user_id       varchar(50),
   update_user_id       varchar(50),
   primary key (id)
);

alter table t_sm_id comment '系统ID表';

 6、newid定义函数(MYSQL自定义函数)

-- QQ: 380105206  WECHAT: 13316098767

DROP FUNCTION IF EXISTS newid;

DELIMITER $$$

CREATE FUNCTION newid(
	P_SYSCODE VARCHAR(20)
)
RETURNS varchar(50)
BEGIN
	DECLARE v_syscode VARCHAR(20); -- ID分组编码
	DECLARE v_last_id VARCHAR(50); -- 最新的ID
	DECLARE v_last_id_format VARCHAR(100); -- 最新的ID
	DECLARE v_id_len INT ;   -- ID最小填充长度
	DECLARE v_id_sep_len INT ; --  ID 分组长度
	
	SET v_syscode = IFNULL(P_SYSCODE, 'ID'); -- NULL默认取'ID'
	SET v_syscode = CASE WHEN v_syscode = '' THEN 'ID' ELSE v_syscode END; -- '' 默认取'ID'
	
	SET v_id_len = 9;   -- ID最小填充长度
	SET v_id_sep_len = 3; --  ID 分组长度
	
	-- 如果没有定义编码,则应该先定义,但可能产生并发问题,所以插入是还应增加判定条件
	-- ID = SYSCODE
	IF NOT EXISTS (SELECT * FROM t_sm_id WHERE id = v_syscode) THEN
		INSERT INTO t_sm_id
		(
		   id                  ,-- varchar(50) not null comment 'rowid',
		   syscode             ,-- varchar(20) comment '功能编码',
		   last_id             ,-- bigint comment '最新id',
		   remark              ,-- varchar(200) comment '备注',
		   create_time         ,-- varchar(30),
		   update_time         ,-- varchar(30),
		   create_user_id      ,-- varchar(50),
		   update_user_id       -- varchar(50),
		)
		SELECT v_syscode, v_syscode, 0, '', NOW(), NOW(), 'SYS', 'SYS'
			WHERE NOT EXISTS (SELECT * FROM t_sm_id WHERE id = v_syscode);
	END IF;
	
	-- 更新ID
	UPDATE t_sm_id SET last_id=LAST_INSERT_ID(last_id+1), update_time = NOW() WHERE id = v_syscode;
	SET v_last_id = LAST_INSERT_ID();
	
	
	-- 返回结果
	
	-- 格式1:编码 + '-' + 序列号
	-- RETURN CONCAT( v_syscode, '-', LAST_INSERT_ID() );
	
	-- 格式2:6位0 左填充
	-- RETURN CONCAT( v_syscode, '-', LPAD( v_last_id, 6, '0') );
	
	-- 格式3:9 位0 左填充
	SET v_last_id = LPAD( v_last_id, v_id_len, '0');
	SET v_last_id_format = (SELECT REPLACE(
			GROUP_CONCAT(
				SUBSTRING(v_last_id, IDX * v_id_sep_len + 1, v_id_sep_len)
				)
			, ',', '-')
		-- , SUBSTRING('7654769877827788', IDX * 4 + 1, 4)
	FROM (SELECT 0 AS idx UNION SELECT 1 AS idx UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) t
	WHERE IDX < LENGTH(v_last_id) / v_id_sep_len);
	
	RETURN CONCAT( v_syscode, '-', v_last_id_format );
END

$$$

select newid('USER'), LPAD(4, 3, '0') ;
select newid(null), newid('USER'), newid('EQUIP');
SELECT * FROM t_sm_id;

7、简单测试了一下性能,因为要更新表,速度不是太快,如果要生成的ID比较多,建议调整ID步长,或者将ID步长作为参数从外面传入也可:

MySQL ID 自定义函数全自动生成 newid_第4张图片

不足之处或建议意见,请QQ:380105206 或者wx: 13316098767 或 [email protected] 

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