項目中使用mysql數據庫,需要使用自增序列號生成合同編號,編號按年份每年更新,且根據合同模板不同需使用多個自增序列。爲了考慮拓展性,也方便其他業務使用序列,使用了序列表進行集中管理,使用函數操作序列。
解決思路
currval(name)
函數獲取當前序列值。nextval(name)
函數獲取下一個序列值,即先自增value更新後再調用currval(name)
。nextvalForYear(name)
函數適用於按年份每年更新重置value值的場景。setval(name,value)
函數根據傳入的參數手動重置value。- 附: 合同編號的字符串拼接函數
CONCAT(str1,str2,…)
:字符串拼接函數LPAD(str,len,padstr)
:字符串左填充函數RPAD(str,len,padstr)
:字符串右填充函數
例: 拼接格式 - 2020 xxxx第C0001號
//使用了左填充函數LPAD - 0001
select concat(YEAR(NOW()), ' ', #{contractTplName}, '第C', LPAD(nextval(#{seqName}),4,0), '號')
1. 創建Sequence管理表 seq_manage
DROP TABLE IF EXISTS seq_manage;
CREATE TABLE seq_manage (
seq_name VARCHAR(50) NOT NULL,
current_value INT NOT NULL,
increment INT NOT NULL DEFAULT 1,
year INT(4),
PRIMARY KEY (seq_name)
) ENGINE=InnoDB;
2. 取當前值 currval(name)
DROP FUNCTION IF EXISTS currval;
DELIMITER $
CREATE FUNCTION currval (name VARCHAR(50))
RETURNS INTEGER
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE value INTEGER;
SET value = 0;
SELECT current_value INTO value
FROM seq_manage
WHERE seq_name = name;
RETURN value;
END
$
DELIMITER ;
3. 取下一個值 nextval(name)
DROP FUNCTION IF EXISTS nextval;
DELIMITER $
CREATE FUNCTION nextval (name VARCHAR(50))
RETURNS INTEGER
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
UPDATE seq_manage
SET current_value = current_value + increment
WHERE seq_name = name;
RETURN currval(name);
END
$
DELIMITER ;
4. 取下一個值 nextvalForYear(name)
(按年份每年自動重置value)
DROP FUNCTION IF EXISTS nextvalForYear;
DELIMITER $
CREATE FUNCTION nextvalForYear (name VARCHAR(50))
RETURNS INTEGER
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
set @year = (select year from seq_manage WHERE seq_name = name);
IF YEAR(NOW()) > @year THEN
UPDATE seq_manage
SET current_value = 1, year = YEAR(NOW())
WHERE seq_name = name;
RETURN currval(name);
ELSE
UPDATE seq_manage
SET current_value = current_value + increment
WHERE seq_name = name;
RETURN currval(name);
END IF;
END
$
DELIMITER ;
5. 更新當前值 setval(name,value)
DROP FUNCTION IF EXISTS setval;
DELIMITER $
CREATE FUNCTION setval (name VARCHAR(50), value INTEGER)
RETURNS INTEGER
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
UPDATE seq_manage
SET current_value = value
WHERE seq_name = name;
RETURN currval(name);
END
$
DELIMITER ;
測試相關函數:
INSERT INTO seq_manage VALUES ('test', 0, 1);
--添加一個sequence,設置名稱爲'test',初始值爲0,以及每次的自增值爲1。
--如果需要按年份更新,則還需設置year字段初始值,獲取序列時則調用nextvalForYear(name)函數即可
SELECT SETVAL('test', 10);
---設置'test'序列的初始值,這裏設置test的初始值爲10
SELECT CURRVAL('test');
--查詢'test'序列的當前值
SELECT NEXTVAL('test');
--查詢'test'序列的下一個值,不會每年重置value值
SELECT nextvalForYear('test');
--查詢'test'序列的下一個值,每年會更新重置value值
--可以考慮只使用nextvalForYear(name)函數,不用再創建NEXTVAL(name)函數。因爲當序列不需要每年更新時,只需此序列的year字段爲null即可。