使用PreparedStatement.RETURN_GENERATED_KEYS时出现SQLException

发布于 2025-01-04 07:26:31 字数 941 浏览 3 评论 0原文

这是有问题的代码块:

String sq = "INSERT INTO survey (session_id, character_id, timestamp) VALUES (?,?,?)";
PreparedStatement sadd = conn.prepareStatement(sq, PreparedStatement.RETURN_GENERATED_KEYS);
sadd.setLong(1, sessionId);
sadd.setLong(2, character_id);
sadd.setString(3, dateTime);
int affectedrows = sadd.executeUpdate();

//get the ID
long resultId = 0;
ResultSet key = sadd.getGeneratedKeys();
if (key.next()) {
    resultId = key.getLong(1);
}

这个查询在没有 PreparedStatement.RETURN_GENERATED_KEYS 选项的情况下工作正常,但是当我突然添加它时 executeUpdate() 抛出异常:

com.microsoft.sqlserver.jdbc.SQLServerException:已生成更新结果集。

如果我取出 PreparedStatement.RETURN_GENERATED_KEYS ,它会再次正常工作。出于沮丧,我将 executeUpdate() 更改为 executeQuery() 只是为了看看是否可以取回密钥,但出现了无法获取密钥的异常,因为语句必须首先执行。

如何获取生成的密钥?我正在使用 SQL Server 2008 和最新的 JDBC 驱动程序。

This is the code block in question:

String sq = "INSERT INTO survey (session_id, character_id, timestamp) VALUES (?,?,?)";
PreparedStatement sadd = conn.prepareStatement(sq, PreparedStatement.RETURN_GENERATED_KEYS);
sadd.setLong(1, sessionId);
sadd.setLong(2, character_id);
sadd.setString(3, dateTime);
int affectedrows = sadd.executeUpdate();

//get the ID
long resultId = 0;
ResultSet key = sadd.getGeneratedKeys();
if (key.next()) {
    resultId = key.getLong(1);
}

This query worked fine without the PreparedStatement.RETURN_GENERATED_KEYS option, but when I add it suddenly executeUpdate() throws an exception:

com.microsoft.sqlserver.jdbc.SQLServerException: A result set was generated for update.

If I take the PreparedStatement.RETURN_GENERATED_KEYS out, it works again fine. Out of frustration, I changed executeUpdate() to executeQuery() just to see if I could get the key back and got an exception that it can't get keys because the statement must be executed first.

How can I get the generated key? I am using SQL Server 2008 and the latest JDBC driver.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

栩栩如生 2025-01-11 07:26:31

对我来说看起来像是一个驱动程序错误。

您应该从这里尝试更新的 4.0 驱动程序 -> http://www.microsoft.com/download/en/details.aspx ?id=11774

如果这不起作用,一种解决方法是创建一个“插入”存储过程并将生成的 id 作为存储过程输出参数返回。

Looks like a driver bug to me.

You should try a newer 4.0 driver from here -> http://www.microsoft.com/download/en/details.aspx?id=11774

If that does not work, one work around would be to create an 'insert' stored procedure and return the generated id as a stored procedure output parameter.

泼猴你往哪里跑 2025-01-11 07:26:31

看起来像一个错误。你能尝试一下更丑陋的选择吗?

  String dateTimeS = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm").format(dateTime);
  String sq = "INSERT INTO survey (session_id, character_id, timestamp) "
          + "VALUES (" + sessionId + ", " + character_id + ", '" + dateTimeS + "')";
  Statement sadd = conn.createStatement();
  int affectedrows = sadd.executeUpdate(sq, Statement.RETURN_GENERATED_KEYS);

Looks like a bug. Could you give the uglier alternative a try?

  String dateTimeS = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm").format(dateTime);
  String sq = "INSERT INTO survey (session_id, character_id, timestamp) "
          + "VALUES (" + sessionId + ", " + character_id + ", '" + dateTimeS + "')";
  Statement sadd = conn.createStatement();
  int affectedrows = sadd.executeUpdate(sq, Statement.RETURN_GENERATED_KEYS);
不甘平庸 2025-01-11 07:26:31

我在 4.0 和 4.0 上也遇到同样的问题4.1 JDBC 驱动程序。一段时间后,自动编号表上的插入将给出“已生成用于更新的结果集”。随机的。我使用连接池,不知何故,驱动程序可能会进入这样的状态:executeUpdate 与 Statement.RETURN_GENERATED_KEYS 结合使用不再起作用。我发现在这种状态下,executeQuery 可以解决问题,但在初始状态下,executeQuery 不起作用。这导致我采取以下解决方法:

PreparedStatement psInsert = connection.prepareStatement("INSERT INTO XYZ (A,B,C) VALUES(?,?,?)", Statement.RETURN_GENERATED_KEYS);
ResultSet rs = null;
try {
    psInsert.setString(1, "A");
    psInsert.setString(2, "B");
    psInsert.setString(3, "C");
    Savepoint savePoint = connection.setSavepoint();
    try {
        psInsert.executeUpdate();
        rs = psInsert.getGeneratedKeys();
    } catch (SQLServerException sqe)
    {
        if (!sqe.getMessage().equals("A result set was generated for update."))
            throw sqe;
        connection.rollback(savePoint);
        rs = psInsert.executeQuery();
    }
    rs.next();
    idField = rs.getInt(1);
} finally {
    if(rs != null)
        rs.close();
    psInsert.close();
}

I'm having the same issue with the 4.0 & 4.1 JDBC drivers. After a while an insert on a autonumber table would give a "A result set was generated for update." at random. I use connection pooling and somehow the driver can get into a state where executeUpdate in combination with Statement.RETURN_GENERATED_KEYS doesn't work anymore. I found out that in this state an executeQuery does the trick, but in the initial state executeQuery does not work. This lead me to the following workaround:

PreparedStatement psInsert = connection.prepareStatement("INSERT INTO XYZ (A,B,C) VALUES(?,?,?)", Statement.RETURN_GENERATED_KEYS);
ResultSet rs = null;
try {
    psInsert.setString(1, "A");
    psInsert.setString(2, "B");
    psInsert.setString(3, "C");
    Savepoint savePoint = connection.setSavepoint();
    try {
        psInsert.executeUpdate();
        rs = psInsert.getGeneratedKeys();
    } catch (SQLServerException sqe)
    {
        if (!sqe.getMessage().equals("A result set was generated for update."))
            throw sqe;
        connection.rollback(savePoint);
        rs = psInsert.executeQuery();
    }
    rs.next();
    idField = rs.getInt(1);
} finally {
    if(rs != null)
        rs.close();
    psInsert.close();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文