編碼的世界 / 優質文選 / 歷史

MYSQL 存儲過程 生成唯一流水號


2022年7月08日
-   

采用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);      來作為中轉解決問題。


熱門文章