Advertisement

mysql自增函数_在MySQL中创建实现自增的序列(Sequence)的教程

阅读量:

本文主要阐述了在MySQL环境中构建自增序列的方法,并提供了两个具体案例以供参考。详细说明了两个具体案例,并对一些潜在问题进行了简要分析。如需进一步了解,请参考上述内容。

项目应用中,曾有以下一个场景:

在接口中需要生成一个int类型的流水编号,在受多线程模式影响的情况下,在采用时间戳作为唯一标识时可能会出现重复的情况(这种情况发生的概率很低)。

所以想到了利用一个独立的自增的sequence来解决该问题。

当前数据库为:mysql

由于MySQL和Oracle之间存在显著差异,并不能直接使用sequence关键字来生成唯一序列值;因此,在这种情况下,必须创建一张表以模拟序列功能,并按照下面的SQL语句进行操作:

第一步:创建--Sequence 管理表

DROP TABLE IF EXISTS sequence;

CREATE TABLE sequence (

name VARCHAR(50) NOT NULL,

current_value INT NOT NULL,

increment INT NOT NULL DEFAULT 1,

PRIMARY KEY (name)

) ENGINE=InnoDB;

第二步:创建--取当前值的函数

DROP FUNCTION IF EXISTS currval;

DELIMITER $

CREATE FUNCTION currval (seq_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 sequence

WHERE name = seq_name;

RETURN value;

END

$

DELIMITER ;

第三步:创建--取下一个值的函数

DROP FUNCTION IF EXISTS nextval;

DELIMITER $

CREATE FUNCTION nextval (seq_name VARCHAR(50))

RETURNS INTEGER

LANGUAGE SQL

DETERMINISTIC

CONTAINS SQL

SQL SECURITY DEFINER

COMMENT ''

BEGIN

UPDATE sequence

SET current_value = current_value + increment

WHERE name = seq_name;

RETURN currval(seq_name);

END

$

DELIMITER ;

第四步:创建--更新当前值的函数

DROP FUNCTION IF EXISTS setval;

DELIMITER $

CREATE FUNCTION setval (seq_name VARCHAR(50), value INTEGER)

RETURNS INTEGER

LANGUAGE SQL

DETERMINISTIC

CONTAINS SQL

SQL SECURITY DEFINER

COMMENT ''

BEGIN

UPDATE sequence

SET current_value = value

WHERE name = seq_name;

RETURN currval(seq_name);

END

$

DELIMITER ;

第五步:测试函数功能

完成上述四个步骤后,在以下数据中配置所需的sequence名称,并同时设置初始值、当前值以及下一个值

INSERT INTO sequence VALUES ('TestSeq', 0, 1);加上一个sequence名称和初始值,并指定自增幅度

SELECT SETVAL('TestSeq', 10);---设置指定sequence的初始值

SELECT CURRVAL('TestSeq');--查询指定sequence的当前值

SELECT NEXTVAL('TestSeq');--查询指定sequence的下一个值

在Java代码中,可以直接生成SQL语句以获取下一个数值,并从而确保了流水号的唯一性。

贴出部分代码(已测试通过)

public void testGetSequence() {

Connection conn = JDBCUtils.getConnection(url, userName, password);

String sql = "SELECT CURRVAL('TestSeq');";

PreparedStatement ptmt = null;

ResultSet rs = null;

try {

ptmt = conn.prepareStatement(sql);

rs = ptmt.executeQuery();

int count = 0;

while (rs.next()) {

count = rs.getInt(1);

}

System.out.println(count);

} catch (SQLException e) {

e.printStackTrace();

} finally {

JDBCUtils.close(rs, ptmt, conn);

}

}

在实际应用场景中,在开发模拟自增序列的方法时,请考虑以下步骤:首先建立一个存储指定序列名称位置的数据表;随后会使用Java语言执行SQL语句来获取并更新该数据表中的相关信息。为了确保该操作具有原子性,请在此方案的基础上加入同步机制(Synchronized)。已完成该功能后未进行测试验证。

Oracle 的 sequence 功能允许多个表和字段共享一个唯一的值。 MySQL 提供自增列作为主键候选元组的有效实现方式。 然而需要注意的是自增列并非无限制的应用。

a. 只能用于表中的一个字段,一张不能同时存在两个以上的自增列 ;

b. 自增列必须被定义为 key ( PK 或 FK ) ;

c. 自增列不能被多个表共用 ;

d. 如果 insert 语句既不包含自增字段也不将值设置为 NULL,则会自动填充。

在不需要字段顺序递增的场景下,可以通过 MySQL 实现序列控制,请让我们深入探讨一下后续的例子:

DROP TABLE IF EXISTS sequence;

-- 建sequence表,指定seq列为无符号大整型,可支持无符号值:0(default)到18446744073709551615(0到2^64–1)。

CREATE TABLE sequence (

name VARCHAR(50) NOT NULL,

current_value BIGINT UNSIGNED NOT NULL DEFAULT 0,

increment INT NOT NULL DEFAULT 1,

PRIMARY KEY (name) -- 不允许重复seq的存在。

) ENGINE=InnoDB;

DELIMITER /

DROP FUNCTION IF EXISTS currval /

CREATE FUNCTION currval(seq_name VARCHAR(50))

RETURNS BIGINT

BEGIN

DECLARE value BIGINT;

SELECT current_value INTO value

FROM sequence

WHERE upper(name) = upper(seq_name); -- 大小写不区分.

RETURN value;

END;

/

DELIMITER ;

DELIMITER /

DROP FUNCTION IF EXISTS nextval /

CREATE FUNCTION nextval (seq_name VARCHAR(50))

RETURNS BIGINT

BEGIN

DECLARE value BIGINT;

UPDATE sequence

SET current_value = current_value + increment

WHERE upper(name) = upper(seq_name);

RETURN currval(seq_name);

END;

/

DELIMITER ;

DELIMITER /

DROP FUNCTION IF EXISTS setval /

CREATE FUNCTION setval (seq_name VARCHAR(50), value BIGINT)

RETURNS BIGINT

BEGIN

UPDATE sequence

SET current_value = value

WHERE upper(name) = upper(seq_name);

RETURN currval(seq_name);

END;

/

DELIMITER ;

在 SQL 中使用序列:

创建序列,往sequence表插入值即可:

mysql> insert into sequence set name='myseq';

查看当前已建序列:

mysql> select * from sequence;

+-------+---------------+-----------+

|name|current_value|increment|

+-------+---------------+-----------+

|myseq|0|1|

+-------+---------------+-----------+

1 row in set (0.00 sec)

获得序列的下一个值,第一次使用,因此值为1:

mysql> select nextval('myseq');

+------------------+

|nextval('myseq')|

+------------------+

|1|

+------------------+

1 row in set (0.00 sec)

全部评论 (0)

还没有任何评论哟~