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

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

时间: 2024-10-11 12:55:53

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

PowerDesigner Mysql 主键自增、初始值、字符集

自增 在你所要设为自增型的键上(比如你的id)双击,弹出一个Column Properties对话框,右下角有一个Identify的选择框,选中它OK,就可以了. 再去查看Preview,就能看到AUTO_INCREMENT. 起始值 默认自增字段从1开始, 如果需要设置一个初始值, 切换到”Physical Options”,界面如下: 字符集及引擎 原文地址:http://jooben.blog.51cto.com/253727/309467 一般建模可能都会用到:powerdesigner

postgresql自增字段初始值的设定

在实际开发中会有这样的需求,想要自己设置表中自增字段的初始值. 比如:有一个your_table表中有一个自增字段id,我们知道,插入数据后,默认是从1开始自增的. 但是假如现在有一个需求,是要求id从100开始插入,那么该怎么实现呢?其实就是一句sql命令的事儿: select setval('your_table_id_seq', 100, false); 执行成功后,进行测试,插入一条数据后,会发现主键id的值会从100开始递增. 原文地址:https://www.cnblogs.com/

MySQL 插入与自增主键值相等的字段 与 高并发下保证数据准确的实验

场景描述: 表t2 中 有 自增主键 id  和 字段v  当插入记录的时候 要求 v与id 的值相等(按理来说这样的字段是需要拆表的,但是业务场景是 只有某些行相等 ) 在网上搜的一种办法是 先获取自增ID SELECT max(id)+1 from t2 然后给v字段插入获取到的值 但是这样的做法在有删除行+调整过自增值的表中是不准确的 于是换个思路 从 information_schema 下手 读取表的信息 INSERT INTO `t2` VALUES ( NULL, ( SELECT

MyBatis insert后返回自增字段的值

如下情况适用支持自增的DB,如MySQL.其他情况参见:MyBatis魔法堂:Insert操作详解(返回主键.批量插入) 1.model public class UserInfo { private int id;//主键自增ID private String userName;//姓名 private String account;//登陆账号 private String password;//密码 } 2.UserInfoMapper.java public interface User

从远程导入表数据时,如何保持自增字段的值不变。

Set Identity_Insert 表名A On ……导入到表名A语句…… Set Identity_Insert 表名A Off

MySQL设置自增字段

1.MySQL每张表只能有1个自增字段,这个自增字段即可作为主键,也可用作非主键使用,但是请注意将自增字段当做非主键使用时必须为其添加唯一索引,否则系统将会报错 1)将自动增长字段设置为主键 CREATE TABLE t1 ( id INT auto_increment PRIMARY KEY, sid INT ); 2)将自动增长字段设置为非主键 CREATE TABLE t2 ( sid INT PRIMARY KEY, id INT auto_increment UNIQUE ); 3)将

对数据库里所有表的自增字段初始化

对数据库存储过程还不是很熟练,一时半会还写不出函数,所以就干脆用php写了个程序. 十几个数据库,每个库里都有几百张表,数据全部被清空了,但是表里的自增字段的值却还是保留着原表里的,要全部一次性的还原到初始值,若是一个表一个表的修改,不知道要改到猴年马月. //在系统库查询需要修改的数据库的表名称 $sysDbName="information_schema"; $dbarray=array("db1","db2","db3"

ORACLE里的自增字段设置

大家都知道吧,这很坑,尤其是用惯了mysql里的自增字段设置,结果oracle里面没有的.oh,no 我用的是12c版本的,它有一个新特性,可以这样设置自增序列,在创建表是,把id设置为自增序列 create table t ( id   number generated by default as identity (start with 1 increment by 1), name    varchar2(20), password varchar2(20), Constraint Pk_

Mysql中自增字段(AUTO_INCREMENT)的一些常识

Mysql中自增字段(AUTO_INCREMENT)的一些常识 在系统开发过程中,我们经常要用到唯一编号.使用过mysql的人都应该知道,mysql有一个定义列为自增的属性:AUTO_INCREMENT. 指定了AUTO_INCREMENT的列必须要建索引,不然会报错,索引可以为主键索引,当然也可以为非主键索引.(不一定要做主键) 1 2 3 mysql> create table t4 (id int auto_increment); ERROR 1075 (42000): Incorrect