码迷,mamicode.com
首页 > 数据库 > 详细

[DB][MySql]关于取得自增字段的值、及@@IDENTITY 与并发性问题

时间:2017-06-04 21:13:41      阅读:289      评论:0      收藏:0      [点我收藏+]

标签:return   from   height   ted   primary   currval   fine   font   provider   

对于刚从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的下一个值


[DB][MySql]关于取得自增字段的值、及@@IDENTITY 与并发性问题

标签:return   from   height   ted   primary   currval   fine   font   provider   

原文地址:http://www.cnblogs.com/lxjshuju/p/6941606.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!