对于刚从Oracle转向MySql的人都会为,MySql中没有Oracle里的Sequence而感到困惑。MySql中没有了Sequence,那么MySql的主键用什么方式来实现最好呢?
主要有以下几种方式:
1、自增字段作为主键。【推荐方案】
MySql虽然比Oracle少了Sequence,但是多了字段的自增长特性。
插入完了以后可以通过执行【SELECT @@IDENTITY】获取上一条插入语句中生成的自增长字段的值。
这个语句很特别,没有关联到特定的SQL语句,会 让人感觉迷糊,他到底是怎么获取值的。在并发情况下会不会获取其他线程执行后的值。
答案是有可能的,但是不用怕、是可控的。只有不当的编码才会导致取到其他线程的值。先来说一下原理:
- SUMMARY
- The Jet OLE DB version 4.0 provider supports the SELECT @@Identity query that allows you to retrieve the value of the auto-increment field generated on your connection. Auto-increment values used on other connections to your database do not affect the results of this specialized query. This feature works with Jet 4.0 databases but not with older formats.
大致意思是【SELECT @@IDENTITY】获取的是当前数据库连接的前一次执行的值。其他连接执行的值不会影响当前线程。时下流行的框架(如Spring-jdbc、mybatis、hibernate)的数据库连接都是存在ThreadLocal中的、是线程隔离的,所以不会获取到其他线程中的【SELECT @@IDENTITY】值。当多线程编程时、强制把数据库连接传给各个线程同时执行时才会取到其他线程的【SELECT @@IDENTITY】。
2、在MySql中模拟Sequence
第一步:创建--Sequence 管理表
- DROP TABLE IF EXISTS sequence;
- CREATE TABLE WFO_SEQ(
- 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 WFO_SEQ
- 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
- DECLARE C_V INTEGER;
- UPDATE WFO_SEQ SET CURRENT_VALUE = CURRENT_VALUE + INCREMENT WHERE NAME = SEQ_NAME;
- SET C_V = CURRVAL(SEQ_NAME);
- IF C_V = -1 THEN
- INSERT INTO WFO_SEQ(NAME, CURRENT_VALUE, INCREMENT)
- VALUES(SEQ_NAME, 1, 1);
- RETURN 1;
- END IF;
- RETURN C_V;
- 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 WFO_SEQ
- SET current_value = value
- WHERE name = seq_name;
- RETURN currval(seq_name);
- END
- $
- DELIMITER ;
第五步:测试函数功能
SELECT SETVAL('TestSeq', 10);---设置指定sequence的初始值
SELECT CURRVAL('TestSeq');--查询指定sequence的当前值
SELECT NEXTVAL('TestSeq');--查询指定sequence的下一个值
相关推荐
10. **uuid.string**:与uuid.hex类似,但不编码,直接以16字符的字符串表示,可能在某些数据库中存在问题。 在选择主键生成策略时,需要考虑数据库特性、并发插入性能以及系统的具体需求。例如,对于并发插入要求...
在SQL中,`AUTO_INCREMENT`(在MySQL中)或`IDENTITY`(在SQL Server中)关键字用于创建一个整数字段,该字段的值在每次插入新记录时会自动递增。这对于主键字段尤其有用,因为它们需要确保唯一性且无需手动输入。 假设...
当设置`strategy=GenerationType.IDENTITY`时,实体的主键将由数据库自动生成,这通常适用于支持自动增长字段的数据库,如HSQL、SQL Server、MySQL、DB2和Derby等。这种方式简洁高效,但需要数据库级别的支持。 第...
Oracle这类没有自增字段的则不支持。 例子:<id name="id" column="id"><generator class="identity" /> 4. Native主键生成策略 Native主键生成策略是由Hibernate根据使用的数据库自行判断采用identity、hilo、...
- **increment**: 自动递增,适用于支持自增特性的数据库如 MySQL, 但不适用于并发场景。 - **seqhilo**: 高低位算法,适合多线程环境,性能较好。 - **identity**: 使用数据库自身的自动增长机制,适用于 MySQL, ...
- **实现原理**: 在使用`identity`方式时,开发者需要在数据库表的设计中为主键字段指定自动增长属性(例如MySQL中的`AUTO_INCREMENT`)。 - **比较分析**: - **灵活性**: `native`提供更高的灵活性,因为它可以...
需要注意的是,在多实例并发访问同一数据库的情况下,可能会导致主键重复的问题。 ##### 5. identity - **定义**:采用数据库提供的主键生成机制,例如 DB2、SQL Server 和 MySQL 中的主键生成机制。 - **应用场景...