【问题标题】:executeUpdate() returns always 1 with MERGE statementexecuteUpdate() 使用 MERGE 语句始终返回 1
【发布时间】:2021-11-01 18:31:56
【问题描述】:

ExecuteUpdate() 总是返回 1。请提出建议并感谢任何输入。

程序:

PROCEDURE INSERT_USER_PREFERENCES(owner_id_var varchar2, stripeid_var varchar2, type_var varchar2, metadata_var CLOB) AS
BEGIN
    MERGE INTO CXO_USER_PREFERENCES d
    USING(SELECT stripeid_var id FROM dual) s
    ON (d.stripe_id = s.id)
    WHEN NOT MATCHED THEN
        INSERT (OWNER_ID, STRIPE_ID, PREF_TYPE, METADATA, CREATED_DATE )
        VALUES(owner_id_var, stripeid_var, type_var, metadata_var, CURRENT_TIMESTAMP);

    COMMIT;
END  INSERT_USER_PREFERENCES;

Java 代码:

try (CallableStatement stmt = connection.prepareCall(CREATE_USER_PREF_SQL)) {
        SQLParameterMapper sqlParamMapper = new SQLParameterMapper(CREATE_USER_PREF_SQL);
        sqlParamMapper.setString(stmt, ":ownerId", userName);
        sqlParamMapper.setCharacterStream(stmt, ":metadata", reader, metadata.length());
        sqlParamMapper.setString(stmt, ":stripeId", stripeId);
        sqlParamMapper.setString(stmt, ":type", userPreference.getType());

        // invoke the database
        int value = stmt.executeUpdate();
        return value;
    } catch (SQLException e) {
        throw e;
    }

stmt.executeUpdate() - 总是返回 1,即使插入只发生一次。感谢对此的任何投入。理想情况下,如果没有插入或错误,它应该返回 0 或任何异常跟踪。请建议。**

【问题讨论】:

  • 也许您在将代码复制到问题时出错了,但 PL/SQL 过程中的 MERGE 语句缺少 WHEN MATCHED 子句。这意味着 MERGE 只执行一次 INSERT。您在问题中写道,只执行了一次 INSERT。因此我会说你已经回答了你自己的问题。
  • 谢谢。 WHEN MATCHED 子句是强制性的吗?在这里,我想在它不匹配时将记录插入数据库中。那么现在发生了什么: 1. 如果将记录插入到表中,则 stmt.executeUpdate() 将在下次检查并发现 (d.stripe_id = s.id) 和记录存在该记录时返回 1不会被插入到数据库中,但 stmt.executeUpdate() 仍然返回 1。我在这里遗漏了什么吗?请建议。
  • 我不懂Java,但你确定executeUpdate() 的返回值是合并的行数吗?我看不出它怎么会知道。当然,它只知道它已经成功调用了一个过程。即使它在调用后检查sql%rowcount,也会被commit 覆盖。
  • 感谢您的回复。我在这里寻找的是:假设我有 2 个 VM(虚拟机)/2 个用户,试图同时插入记录。当 User1 尝试在表中插入记录时:查询应该检查记录是否存在,然后允许用户插入。同时,如果 user2 尝试插入,则不应允许他插入。更准确地说,它有助于阻止并发插入到表中。谢谢,期待对此的投入。 @威廉罗伯逊
  • 也许程序应该返回通过 OUT 参数合并的行数。

标签: java sql database oracle merge


【解决方案1】:

我们可以将列设为主键。现在,当多个 VM 尝试执行时,另一个会抛出 Unique Integrity 异常,在 catch 块中,我们可以读取 SQLException。一旦我们读取了 SQLException,我们也可以读取 sqlstate,我们可以根据 sqlstate 执行所需的操作。

下面的示例代码

     if (e instanceof SQLException) {
            String sqlState = ((SQLException) e).getSQLState();
            if (sqlState.equalsIgnoreCase("08000") || sqlState.equalsIgnoreCase("08006")) {
                logger.error("POD DB is down with the sql state:" + sqlState);
                return true;
            }
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 2017-08-10
    • 2018-07-02
    • 1970-01-01
    相关资源
    最近更新 更多