您的位置:首页 > 数据库 > MySQL

MYSQL 存储过程 生成唯一流水号

2016-11-14 22:23 477 查看
采用mysql存储过程生成唯一流水号功能,支持并发。

项目中需要生产出库单的流水号,之前用了很多方法都无法解决并发时流水号重复的问题。

直到看见csdn上《关于生成并发唯一性流水号的解决方案》这篇文章,茅塞顿开,作者写的太好了。

尤其是使用update来进行锁定表内容,大大降低了代码难度。因为项目采用的是mysql数据库,因此采用mysql的存储过程重新写了一边。

1 创建数据库: sys_sno

CREATE TABLE `sys_sno` (
`sCode` varchar(50) DEFAULT NULL,
`sName` varchar(100) DEFAULT NULL,
`sQz` varchar(50) DEFAULT NULL,
`sValue` varchar(80) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;




DELIMITER $$

USE `hrpdb`$$

DROP PROCEDURE IF EXISTS `GetSerialNo`$$

CREATE DEFINER=`root`@`localhost` PROCEDURE `GetSerialNo`(IN tsCode VARCHAR(50),OUT result VARCHAR(200) )
BEGIN

DECLARE  tsValue  VARCHAR(50);
DECLARE  tdToday  VARCHAR(20);
DECLARE  nowdate  VARCHAR(20);
DECLARE  tsQZ     VARCHAR(50);
DECLARE t_error INTEGER DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET t_error=1;
START TRANSACTION;
UPDATE sys_sno  SET sValue=sValue WHERE sCode=tsCode;
SELECT sValue INTO tsValue  FROM sys_sno  WHERE sCode=tsCode;
SELECT sQz INTO tsQZ FROM sys_sno WHERE sCode=tsCode ;
-- 因子表中没有记录,插入初始值
IF tsValue IS NULL  THEN
SELECT CONCAT(DATE_FORMAT(NOW(),'%y%m'),'0000001') INTO tsValue;
UPDATE sys_sno SET sValue=tsValue WHERE sCode=tsCode ;
SELECT CONCAT(tsQZ,tsValue) INTO result;
ELSE
SELECT  SUBSTRING(tsValue,1,4) INTO tdToday;
SELECT  CONVERT(DATE_FORMAT(NOW(),'%y%m'),SIGNED) INTO nowdate;
IF tdToday = nowdate THEN
SET  tsValue=CONVERT(tsValue,SIGNED) + 1;
ELSE
SELECT CONCAT(DATE_FORMAT(NOW(),'%y%m') ,'0000001') INTO tsValue ;
END IF;
UPDATE sys_sno SET sValue =tsValue WHERE sCode=tsCode;
SELECT CONCAT(tsQZ,tsValue) INTO result;
END IF;

IF t_error =1 THEN
ROLLBACK;
SET result = 'Error';
ELSE
COMMIT;
END IF;
SELECT  result ;
END$$

DELIMITER ;


因为实际项目中流水号是按照月份来生成的,因此使用
DATE_FORMAT(NOW(),'%y%m')


特别注意:

2016年11月14日时 '1611140000001'

SUBSTRING(tsValue,1,6)   后的值与   DATE_FORMAT(NOW(),'%y%m') 相等

SUBSTRING(tsValue,1,4)   后的值与   DATE_FORMAT(NOW(),'%y')  不相等!!

原因是1614强制赋值给datetime类型时 其不是一个有效的datetime值 因此 与  DATE_FORMAT(NOW(),'%y')  不同。

所以项目中使用

 DECLARE  tdToday  VARCHAR(20);     

 DECLARE  nowdate  VARCHAR(20);      来作为中转解决问题。




                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息