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

採用mysql存儲過程生成唯一流水號功能,支持併發。

項目中需要生產出庫單的流水號,之前用了很多方法都無法解決併發時流水號重複的問題。

直到看見csdn上《關於生成併發唯一性流水號的解決方案》這篇文章,茅塞頓開,作者寫的太好了。

尤其是使用update來進行鎖定表內容,大大降低了代碼難度。因爲項目採用的是mysql數據庫,因此採用mysql的存儲過程重新寫了一邊。


創建數據庫: 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);      來作爲中轉解決問題。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章