【问题标题】:Stored Procedure for UPSERT functionalityUPSERT 功能的存储过程
【发布时间】:2013-01-24 23:04:58
【问题描述】:

下面是我的表,其中ID column is Primary Key。其他两列是字符串。

我正在使用一个名为 XpressMP 的新数据库。

Column Name                
-------
ID             PrimaryKey                 
SEARCHES       String
ACCOUNT        String

我正在尝试在此处实现UPSERT 的功能-

If ID doesn't exists here then insert a new record.
And ID exists then update the record.

我知道如果我正在使用 Oracle,那么我可以使用 MERGE sql 命令,但该数据库不支持 MERGE,并且目前没有其他命令。但我相信我可以用Stored Procedure 做同样的事情。

谁能提供一些建议,我如何使用存储过程做同样的事情?因为存储过程将在那里工作。

更新:-

public final static String INSERT = "BEGIN"
+" INSERT INTO TABLE (ID, SEARCHES, ACCOUNT) VALUES (?, ?, ?)"
+" EXCEPTION"
+" WHEN DUP_VAL_ON_INDEX THEN"
+" UPDATE TABLE"
+" SET SEARCHES = ?, ACCOUNT = ?"
+" WHERE ID = ?"
+" END";

每当我尝试像这样执行上述存储过程时

preparedStatement = dbConnection.prepareStatement(INSERT);

preparedStatement.setString(1, String.valueOf(userId));
preparedStatement.setString(2, Constants.getaAccount(userId));
preparedStatement.setString(3, Constants.getaAdvertising(userId));
preparedStatement.executeUpdate();

我得到异常?这是执行它的正确方法吗?

【问题讨论】:

    标签: sql database stored-procedures plsql


    【解决方案1】:

    嗯,我认为你必须以传统的方式来做。

    如果行不存在 插入 别的 更新

    【讨论】:

    • 是的,我已经知道了:)。但那是什么传统方式呢?存储过程对吗?
    • 这是你的设计决定。我会推荐存储过程。
    • 是的,我也是这么想的。您能否提供任何与存储过程相关的示例,这些示例适用于我的情况?
    【解决方案2】:

    您可以使用DUP_VAL_ON_INDEX 异常来处理它。
    您可以在您的程序中添加以下代码,这应该符合您的要求。

    CREATE OR REPLACE PROCEDURE TABLE_UPSERT (v_id IN NUMBER,
                                              v_searches IN VARCHAR2(20),
                                              v_account IN VARCHAR2(20)) AS
    BEGIN
      INSERT INTO table (id, searches, account) VALUES (v_id, v_searches, v_account) ;
    EXCEPTION
      WHEN DUP_VAL_ON_INDEX THEN
        UPDATE TABLE
        SET searches = v_searches, account = v_account
        WHERE id = v_id;
    END;
    /
    

    您可以阅读有关 DUP_VAL_ON_INDEX 异常 herehere 的更多信息。


    另一种选择是在检查计数后插入或更新数据。

    DECLARE
      l_count number;
    BEGIN
      SELECT count(*) 
      INTO l_count
      FROM table 
      WHERE id = (value);
    
      IF l_count = 0 THEN
        INSERT into table VALUES ....;
      ELSE
        UPDATE table SET searches = .., account = ..;
      END IF;
    END;
    

    【讨论】:

    • 感谢 Orangecrush 的帮助。将查看DUP_VAL_ON_INDEX。因为我将使用 java 来调用这个存储过程。所以我修改了你的 SP 这样的工作。 BEGIN INSERT INTO TABLE (ID, SEARCHES, ACCOUNT) VALUES (?, ?, ?) ; EXCEPTION WHEN DUP_VAL_ON_INDEX THEN UPDATE TABLE SET SEARCHES = ?, ACCOUNT = ? WHERE ID = ?; END;。它应该工作正常吗?当我填充... ?标记。
    • @FarhanJamal 是的,如果您在调用此过程时在 java 中正确处理变量,应该可以工作。试一试。如果您想尝试该代码,还提供了编辑并提供了一个更易于理解的代码。但我建议使用DUP_VAL_ON_INDEX
    • @FarhanJamal 我想你会使用SP (?,?,?)从java调用这个SP。您不能将? 用于 PL/SQL 过程中的变量值。
    • 我用更多细节更新了这个问题。我想,我做错了,这就是我得到异常的原因。如果我做错了什么,请告诉我?
    • Aaah.. 现在是有意义的,这意味着,我需要首先执行这个存储过程,以便它在数据库中创建,然后我需要从 Java 程序中调用它。正确的?那么如何在我的数据库中创建这个存储过程呢?
    【解决方案3】:

    我在这里同意@tabish。你必须用传统的方式来做。 您建议的方式我认为您会造成更大的伤害-您对源表中的每一行(到目标表或 ERR 表)执行插入,然后执行附加更新。 在最坏的情况下,当您必须更新所有行时,您将执行两倍的 dml 操作。 在我的书中,这不是一个好主意。 祝你好运。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-16
      • 1970-01-01
      相关资源
      最近更新 更多