[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》 | 王小鸭自动发工资条VBA版
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[转]JDBC取得自动生成的ID

上一篇:[转]在VBA代码中引用Excel工作表中单元格区域的方式小结
下一篇:[转]《中华人民共和国劳动合同法》全文 (2008年1月1日执行)

添加日期:2009/6/4 21:59:22 快速返回   返回列表 阅读4227次
JDBC 3.0才支持这样的写法,否则就使用select last_insert_id()吧……


String psql = "INSERT INTO Employee (name, age, address, isMale, level, Department_ID) VALUES (?, ?, ?, ?, ?, ?)";
PreparedStatement ps  = conn.prepareStatement(psql,Statement.RETURN_GENERATED_KEYS);

ps.setString(1, emp.getName());
ps.setInt(2, emp.getAge());
ps.setString(3, emp.getAddress());
ps.setInt(4, emp.getIsMale());
ps.setInt(5, emp.getLevel());
ps.setInt(6, emp.getDepartment_ID());

ps.executeUpdate();

ResultSet keys = ps.getGeneratedKeys(); // equivalent to "SELECT last_insert_id();"

if(keys.next()) {
    System.out.println(keys.getInt(1));
}



如果有多个字段的值是自动生成的,而且又不明确有多少个,或者插入的不仅仅是一条数据的话,或许可以考虑使用以下方式,即通过获得结果集的元据来操作:

Connection conn = //获得连接...;
Statement st = conn.createStatement();
st.execute(sql, Statement.RETURN_GENERATED_KEYS);
 
ResultSet rs = st.getGeneratedKeys();
ResultSetMetaData rsmd = rs.getMetaData();
int cols = rsmd.getColumnCount();
 
while (rs.next()) {
    for (int i = 1; i < = cols; i++) {
        //处理数据...
    }
}



在JDBC 3.0之前的版本中,PreparedStatement不能绑定主键,如果采用表自增键(如MySql的auto increment或SqlServer的identity)将给获取正确的主键值带来挑战——因为你必须在插入数据后,马上执行另一条获取新增主键的查询语句。表 1给出了不同数据库获取最新自增主键值的查询语句:

表 1 不同数据库获取新增加的主键值 

数据库 获取新增主键的查询语句 
DB2     IDENTITY_VAL_LOCAL() 
Informix     SELECT dbinfo('sqlca.sqlerrd1') FROM <TABLE> 
Sybase     SELECT @@IDENTITY 
SqlServer     SELECT SCOPE_IDENTITY()或SELECT @@IDENTITY 
MySql     SELECT LAST_INSERT_ID() 
HsqlDB     CALL IDENTITY() 
Cloudscape     IDENTITY_VAL_LOCAL() 
Derby     IDENTITY_VAL_LOCAL() 
PostgreSQL     SELECT nextval('<TABLE>_SEQ') 

如果数据库的并发率很高,比如在插入记录后执行查询主键之前,数据库又执行了若干条插入记录的SQL语句,这时,通过表 1 返回的主键值就是最后一条插入语句的主键值,而非我们希望的主键值了。

所以使用查询语句获取表自增键值是不安全的,这也是为什么有些数据库(如 Oracle、Firebird)故意不提供自增键,而只提供序列的原因,序列强制要求你在新增记录前,先获取主键值。

Oracle通过SELECT <SEQUENCE_NAME>.nextval FROM DUAL获取序列的下一个值,而FireBird通过SELECT GEN_ID(<SEQUENCE_NAME> 1) FROM RDB$DATABASE获取序列的下一个值。
 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved