一般使用序列(Sequence)来处理主键字段,在MySQL中是没有序列的,但是MySQL有提供了自增长(increment)来实现类似的目的,但也只是自增,而不能设置步长、开始索引、是否循环等,最重要的是一张表只能由一个字段使用自增,但有的时候我们需要两个或两个以上的字段实现自增(单表多字段自增),MySQL本身是实现不了的。
方案
我们可以用创建一个序列表,使用函数来获取序列的值。
- 创建序列表,参考如下:
drop table if exists SEQUENCE;
/*==============================================================*/
/* Table: SEQUENCE */
/*==============================================================*/
create table SEQUENCE
(
SEQ_NAME varchar(50) not null,
CURRENT_VAL int not null,
INCREMENT_VAL int not null,
primary key (SEQ_NAME)
);
其中,SEQ_NAME - 序列名,CURRENT_VAL - 当前值,INCREMENT_VAL - 步长
- 创建 Mysql 函数,获取当前值 CURRENT_VAL 和下一个值
-- 获取当前值 currval
DROP FUNCTION IF EXISTS currval;
DELIMITER $$
CREATE FUNCTION currval (param_name VARCHAR(50))
RETURNS INT
BEGIN
DECLARE c_value INT DEFAULT 0;
SET c_value = 0;
SELECT CURRENT_VAL into c_value FROM SEQUENCE WHERE SEQ_NAME = param_name;
RETURN c_value;
END $$
DELIMITER ;
-- 获取下一个值 nextval
DROP FUNCTION IF EXISTS nextval;
DELIMITER $$
CREATE FUNCTION nextval (param_name VARCHAR(50))
RETURNS INT
CONTAINS SQL
BEGIN
UPDATE SEQUENCE SET CURRENT_VAL = CURRENT_VAL + INCREMENT_VAL WHERE SEQ_NAME = param_name;
RETURN currval(param_name);
END $$
DELIMITER ;
注意:
1. mysql 的语法要注意分隔符问题,因为 mysql 一遇到分号,它就要自动执行。即,在语句RETURN '';时,mysql解释器就要执行了。这种情况下,就需要使用 DELIMITER 把分隔符换成其它符号,如//或$$。 在一个需要整体执行的末端指定设置的分隔符,达到整体执行的效果。
2. 函数的参数命名,一定不要使用表的字段名,否则不能正常被识别。自己不小心使用了,会遇到整体更新等各种奇葩问题。
- 调用执行
-- 获取当前值
select currval ('my_seq');
-- 获取下一个值
select nextval('my_seq');