设计自增流水规则表
CREATE TABLE `invoice_sequence` (
`rule_code` varchar(20) NOT NULL COMMENT '规则编码',
`prefix` varchar(20) NOT NULL COMMENT '流水号前缀',
`date_format` varchar(20) NOT NULL COMMENT '日期格式',
`number_length` int DEFAULT NULL COMMENT '流水号长度',
`current_date_str` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '当前日期',
`current_number` int DEFAULT NULL COMMENT '流水号位置',
`remark` varchar(255) DEFAULT NULL COMMENT '备注信息',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
PRIMARY KEY (`rule_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='通用自定义自增规则流水号表';
INSERT INTO `invoice_sequence` (`rule_code`, `prefix`, `date_format`, `number_length`, `current_date`, `current_number`, `remark`)
VALUES ('FLRK', 'FLRK', '%Y%m', 4, '202201', 0, '废料入库单据流水号');
create
definer = root@`%` procedure GenerateNewInvoiceNumber(IN p_rule_code varchar(20))
BEGIN
-- 定义接值的参数
DECLARE v_number_length INT; #流水长度
DECLARE v_prefix VARCHAR(20); #流水前缀
DECLARE v_date_format VARCHAR(20); #时间格式化方式
DECLARE v_current_date VARCHAR(20); #上次生成流水的格式化时间
DECLARE v_current_number INT; #上次生成流水的值
DECLARE v_count INT;
#是否存在当前流水规则的CODE
-- 设置事务超时时间为 10 秒
SET innodb_lock_wait_timeout = 10;
START TRANSACTION;
-- 预先获取规则信息
-- 获取流水长度,流水前缀,时间格式化字符串,流水最新的时间
SELECT `number_length`,
`prefix`,
`date_format`,
`current_date_str`,
`current_number`,
count(1)
INTO
v_number_length, v_prefix, v_date_format,v_current_date ,v_current_number,v_count
FROM `invoice_sequence`
WHERE `rule_code` = p_rule_code FOR
UPDATE;
IF v_count = 0 THEN #如果CODE未被查询出来
SIGNAL SQLSTATE '45001'
SET MESSAGE_TEXT = "当前单据CODE不存在配置表中";
END IF;
-- 生成新流水号
SET @newNumber = 0;
SET @tempDataStr = DATE_FORMAT(NOW(), v_date_format);
-- 判断当前日期是否与存储的日期一致
IF v_current_date = @tempDataStr THEN
SET @newNumber = v_current_number + 1;
-- 更新表中的状态
UPDATE `invoice_sequence` SET `current_number` = @newNumber WHERE `rule_code` = p_rule_code;
ELSE
-- 获取当前流水号
SET @newNumber = 1;
-- 更新表中的状态
UPDATE `invoice_sequence`
SET `current_number` = @newNumber,
`current_date_str` = @tempDataStr
WHERE `rule_code` = p_rule_code;
END IF;
-- 格式化新流水号为指定长度
SET @formattedNewNumber = LPAD(@newNumber, v_number_length, '0');
-- 提交事务
COMMIT;
-- 恢复默认事务超时时间
SET innodb_lock_wait_timeout = 50;
-- 最终生成的流水号
SELECT CONCAT(v_prefix, DATE_FORMAT(NOW(), v_date_format), @formattedNewNumber) AS `new_invoice_number`;
END;
- 测试获取流水号
- 并发场景测试
开启10个线程并发生成流水id
顺利生成流水id