JDBC getGeneratedKeys()

时间:2012-11-03 01:10:11

标签: sql jdbc

我从http://docs.oracle.com/javase/1.4.2/docs/guide/jdbc/getstart/preparedstatement.html

获得了以下代码示例

我有三个问题:

  1. 'keyColumn'指的是只有三列--LAST,FIRST,HOME。
  2. 为什么在迭代生成的密钥时使用循环?是否为该一个insert语句返回了多行?
  3. 哪些数据库支持每个表生成多个密钥?
String sql = "INSERT INTO AUTHORS (LAST, FIRST, HOME) VALUES " +
                                     "(?, ?, ?, keyColumn)";

PreparedStatement addAuthor = con.prepareStatement(sql,
                             Statement.RETURN_GENERATED_KEYS);
addAuthor.setString(1, "Wordsworth");
addAuthor.setString(2, "William");
addAuthor.setString(3, "England");

int rows = addAuthor.executeUpdate();

ResultSet rs = stmt.getGeneratedKeys();
if (rs.next()) {
    ResultSetMetaData rsmd = rs.getMetaData();
    int colCount = rsmd.getColumnCount();
    do {
        for (int i = 1; i <= colCount; i++) {
            String key = rs.getString(i);
            System.out.println("key " + i + "is " + key);
        }
    }
    while (rs.next();)
} 
else {
    System.out.println("There are no generated keys.");
}

1 个答案:

答案 0 :(得分:2)

问题1.我认为链接查询中的keyColumn只是示例中的错误。该段中的第二个和第三个示例也包含严重的语法错误。我不会纠缠于此。此文档已完全从最新的Java版本中删除。

问题2.考虑可以产生多个插入行的INSERT INTO ... SELECT ... FROM ...INSERT INTO ... VALUES (...), (...)等语句。此外,一些数据库支持从其他DML返回值(例如UPDATEDELETE),这也会影响多行,这就是您需要考虑循环的原因。在这个具体示例中,没有必要,因为您可以确定只插入一行。

问题3.这个问题有点复杂:

某些数据库(或驱动程序)无法轻易确定实际生成的列是什么。例如,因为数据库没有IDENTITY列,但使用触发器生成密钥。识别生成的密钥将涉及解析表上的所有触发器以检查它是否将生成的值分配给(主键或其他)列,这不容易完成并且容易出错。有时会有多个生成的列(即计算字段等)。作为开发人员,您应该知道您可以或想要返回哪些字段。

由于确定要返回哪些字段很难(或效率低下),因此某些驱动程序(默认情况下)会返回插入(或删除/更新)行的所有列。例如,PostgreSQL和Firebird驱动程序就是这样做的。另一方面,一些驱动程序只返回最后生成的密钥,即使该表不包含标识列(我相信MySQL确实如此,但不是100%确定)。我似乎记得Oracle驱动程序只返回ROWID,让用户可以使用ROWID从数据库中检索实际值。

如果您明确知道要返回哪些列,则可以使用接受column ordinal indicescolumn names数组的替代方法自行指定。虽然并非所有司机都支持这一点。