【问题标题】:Check for existence or catch exception?检查是否存在或捕获异常?
【发布时间】:2012-08-28 06:25:43
【问题描述】:

如果记录存在,我想更新一条记录,如果不存在,我想插入一条新记录。

最好的方法是什么?

执行Select Count(),如果返回零则插入,如果返回则查询记录、修改和更新, 还是我应该尝试查询记录并捕获任何 system.queryexception?

这一切都在 Apex 中完成,而不是通过 REST 或 JS API。

【问题讨论】:

  • upsert 有什么问题?

标签: salesforce apex-code soql


【解决方案1】:

除了这里已经说过的内容之外,您还想在这些情况下使用 FOR UPDATE 来避免 superfell 所指的内容。所以,

Account theAccount;
Account[] accounts = [SELECT Id FROM Account WHERE Name = 'TEST' LIMIT 1 FOR UPDATE];
if(accounts.size() == 1)
   theAccount = accounts[0];
else
   theAccount = new Account();

// Make modifications to theAccount, which is either:
// 1. A record-locked account that was selected OR
// 2. A new account that was just created with new Account()

upsert theAccount;

【讨论】:

  • 这在帐户不存在的情况下不起作用,因为没有要锁定的帐户行。您需要锁定在这两种情况下都存在的父行,或者使用依赖底层数据库索引的 upsert 来做正确的事情。
  • ??你确定吗?如果您查看我的代码,我将首先创建一个新帐户。如果一个不存在,那么新帐户就是使用的那个(插入),但如果一个帐户确实存在,则为 theAccount get 分配该值并执行更新。如果我对它进行更改,也许我的代码会更清晰。现在改...
  • 是的,我确定,您修改后的代码使用了 upsert,因此可以跳过选择开始。
  • 我想我明白你在说什么。我个人尽可能避免执行 count() 和 select,因为它会烧掉 2 个 SOQL 调用而不是 1 个。我修改后的代码实际上与我之前的代码所做的相同——我只是将新的 Account() 实例移动到 else 块,而不是在顶部进行。也许它看起来更清楚,但之前就已经存在了。一般来说,如果您要更新对象中已经存在的任何内容(包括 upsert),您需要先选择它。使用 FOR UPDATE 执行此操作是例外做法,除非我遗漏了什么。
  • 如果您正在进行更新并且您知道新值,则绝对不需要先读取该行。如果新值取决于当前值,那么是的,您应该使用 FOR UPDATE 读取该行。
【解决方案2】:

如果可能的话,您应该使用upsert 调用,一旦您进入并发调用领域,选择然后插入/更新方法就会出现问题,除非您在选择过程中遇到了正确锁定父行的麻烦打电话。

【讨论】:

    【解决方案3】:

    我会尝试使用列表和isEmpty() 函数:

    List<Account> a = [select id from account where name = 'blaahhhh' Limit 1];
    
    if(a.isEmpty()){
        System.debug('#### do insert'); 
    }
    else{
        System.debug('#### do update'); 
    }
    

    【讨论】:

    • 好主意。这种方法有什么原因吗?
    猜你喜欢
    • 2012-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多