您好,欢迎访问一九零五行业门户网

MYSQL获取自增主键【4种方法】_MySQL

bitscn.com
mysql获取自增主键【4种方法】
通常我们在应用中对mysql执行了insert操作后,需要获取插入记录的自增主键。本文将介绍java环境下的4种方法获取insert后的记录主键auto_increment的值:
通过jdbc2.0提供的insertrow()方式
通过jdbc3.0提供的getgeneratedkeys()方式
通过sql select last_insert_id()函数
通过sql @@identity 变量
1. 通过jdbc2.0提供的insertrow()方式
自jdbc2.0以来,可以通过下面的方式执行。
[java] 
statement stmt = null;  
resultset rs = null;  
try {  
    stmt = conn.createstatement(java.sql.resultset.type_forward_only,  // 创建statement  
                                java.sql.resultset.concur_updatable);  
    stmt.executeupdate(drop table if exists autoinctutorial);  
    stmt.executeupdate(                                                // 创建demo表  
            create table autoinctutorial (  
            + prikey int not null auto_increment,  
            + datafield varchar(64), primary key (prikey)));  
    rs = stmt.executequery(select prikey, datafield                 // 检索数据  
       + from autoinctutorial);  
    rs.movetoinsertrow();                                              // 移动游标到待插入行(未创建的伪记录)  
    rs.updatestring(datafield, auto increment here?);              // 修改内容  
    rs.insertrow();                                                    // 插入记录  
    rs.last();                                                         // 移动游标到最后一行  
    int autoinckeyfromrs = rs.getint(prikey);                        // 获取刚插入记录的主键prekey  
    rs.close();  
    rs = null;  
    system.out.println(key returned for inserted row:  
        + autoinckeyfromrs);  
}  finally {  
    // rs,stmt的close()清理  
}  
优点:早期较为通用的做法
缺点:需要操作resultset的游标,代码冗长。
2. 通过jdbc3.0提供的getgeneratedkeys()方式
[java] 
statement stmt = null;  
resultset rs = null;  
try {  
    stmt = conn.createstatement(java.sql.resultset.type_forward_only,  
                                java.sql.resultset.concur_updatable);    
    // ...  
    // 省略若干行(如上例般创建demo表)  
    // ...  
    stmt.executeupdate(  
            insert into autoinctutorial (datafield)  
            + values ('can i get the auto increment field?'),  
            statement.return_generated_keys);                      // 向驱动指明需要自动获取generatedkeys!  
    int autoinckeyfromapi = -1;  
    rs = stmt.getgeneratedkeys();                                  // 获取自增主键!  
    if (rs.next()) {  
        autoinckeyfromapi = rs.getint(1);  
    }  else {  
        // throw an exception from here  
    }   
    rs.close();  
    rs = null;  
    system.out.println(key returned from getgeneratedkeys():  
        + autoinckeyfromapi);  
}  finally { ... }  
这种方式只需要2个步骤:1. 在executeupdate时激活自动获取key; 2.调用statement的getgeneratedkeys()接口
优点:
1. 操作方便,代码简洁
2. jdbc3.0的标准
3. 效率高,因为没有额外访问数据库
这里补充下,
a.在jdbc3.0之前,每个jdbc driver的实现都有自己获取自增主键的接口。在mysql jdbc2.0的driver org.gjt.mm.mysql中,getgeneratedkeys()函数就实现在org.gjt.mm.mysql.jdbc2.staement.getgeneratedkeys()中。这样直接引用的话,移植性会有很大影响。jdbc3.0通过标准的getgeneratedkeys很好的弥补了这点。
b.关于getgeneratedkeys(),官网还有更详细解释:oraclejdbcguide
3. 通过sql select last_insert_id()函数
[java] 
statement stmt = null;  
resultset rs = null;  
try {  
    stmt = conn.createstatement();  
    // ...  
    // 省略建表  
    // ...  
    stmt.executeupdate(  
            insert into autoinctutorial (datafield)  
            + values ('can i get the auto increment field?'));  
    int autoinckeyfromfunc = -1;  
    rs = stmt.executequery(select last_insert_id());             // 通过额外查询获取generatedkey  
    if (rs.next()) {  
        autoinckeyfromfunc = rs.getint(1);  
    }  else {  
        // throw an exception from here  
    }   
    rs.close();  
    system.out.println(key returned from +  
                       'select last_insert_id()': +  
                       autoinckeyfromfunc);  
}  finally {...}  
这种方式没什么好说的,就是额外查询一次函数last_insert_id().
优点:简单方便
缺点:相对jdbc3.0的getgeneratedkeys(),需要额外多一次数据库查询。
补充:
1. 这个函数,在mysql5.5手册的定义是:“returns a bigint (64-bit) value representing the first automatically generated value successfully inserted for an auto_increment column as a result of the most recently executed insert statement.”。文档点此
2. 这个函数,在connection维度上是“线程安全的”。就是说,每个mysql连接会有个独立保存last_insert_id()的结果,并且只会被当前连接最近一次insert操作所更新。也就是2个连接同时执行insert语句时候,分别调用的last_insert_id()不会相互覆盖。举个栗子:连接a插入表后last_insert_id()返回100,连接b插入表后last_insert_id()返回101,但是连接a重复执行last_insert_id()的时候,始终返回100,而不是101。这个可以通过监控mysql连接数和执行结果来验证,这里不详述实验过程。
3. 在上面那点的基础上,如果在同一个连接的前提下同时执行insert,那可能2次操作的返回值会相互覆盖。因为last_insert_id()的隔离程度是连接级别的。这点,getgeneratedkeys()是可以做的更好,因为getgeneratedkeys()是statement级别的。同个connection的多次statement,getgeneratedkeys()是不会被相互覆盖。
4. 通过select @@identity 变量
这个方式和last_insert_id()效果是一样的。官网文档如此表述:“this variable is a synonym for the last_insert_id variable. it exists for compatibility with other database systems. you can read its value with select @@identity, and set it using set identity.” 文档点此
重要补充:
无论是select last_insert_id()还是select @@identity,对于一条insert语句插入多条记录,永远只会返回第一条插入记录的generatedkey.如:
[java] 
insert into t values  
    -> (null, 'mary'), (null, 'jane'), (null, 'lisa');  
last_insert_id(), @@identity都只会返回'mary'所在的那条记录的generatedkey
bitscn.com
其它类似信息

推荐信息