Salesforce:System.LimitException:SOQL查询太多:101

时间:2013-02-12 08:07:30

标签: salesforce force.com soql

几天前一切正常,除了配置文件之外,系统没有进行任何新的更改。

突然我收到了这条错误消息:

  

错误:数据无效。   查看下面的所有错误消息以更正您的数据   Apex触发generateUniqueBidId导致意外异常,请联系您的管理员:generateUniqueBidId:System.LimitException:SOQL查询太多:101

 trigger generateUniqueBidId on Bids__c (before insert) {

    Map<String, String> profilePrefixMap = new Map<String, String>();
    profilePrefixMap.put('Sales User', 'rds');
    profilePrefixMap.put('Super User', 'rds');
    profilePrefixMap.put('Standard User','SU');
    profilePrefixMap.put('System Administrator','SysAdmin');

    String defaultPrefix = ' ';
    User user = [SELECT ProfileId FROM User Where Id = :Userinfo.getUserId() LIMIT 1];
    Profile profile = [SELECT Name FROM Profile Where Id = :user.ProfileId LIMIT 1];
    List<Bids__c> recentBids = [SELECT Id, CreatedById, Bid_unique_label__c From Bids__c WHERE Bid_unique_label__c = NULL];

    /**Logics for updating old Bids with correct Bid_id. May be refactored away when all bids are updated
       Could cause problems if trigger system becomes to complicated. 
    */
    for (Bids__c bid : recentBids){
        String recentProfileName = [SELECT Profile.Name FROM User Where Id = :bid.CreatedById LIMIT 1].Profile.Name;
        String bidId = profilePrefixMap.get(recentProfileName);
        bid.Bid_unique_label__c =  ((bidId == null) ? defaultPrefix : bidId);           
    }
    upsert recentBids;

    for (Bids__c bid : trigger.new){
        String bidId = profilePrefixMap.get(String.valueOf(profile.Name));
        bid.Bid_unique_label__c = ((bidId == null) ? defaultPrefix : bidId);
    }

}

1 个答案:

答案 0 :(得分:3)

循环中有一个SOQL。

for (Bids__c bid : recentBids){
    String recentProfileName = [SELECT Profile.Name FROM User Where Id = :bid.CreatedById LIMIT 1].Profile.Name;
    String bidId = profilePrefixMap.get(recentProfileName);
    bid.Bid_unique_label__c =  ((bidId == null) ? defaultPrefix : bidId);           
}
upsert recentBids;

这是一个性能杀手,实际上我很惊讶限制是100个查询,在触发器上下文中过去不超过20个查询。快速解决您的问题的方法是使用带有“点表示法”的关系查询。这将消除在循环中进行查询的需要。

List<Bids__c> recentBids = [SELECT Id, CreatedBy.Profile.Name, Bid_unique_label__c 
FROM Bids__c 
WHERE Bid_unique_label__c = NULL];

for (Bids__c bid : recentBids){
    String recentProfileName = bid.CreatedBy.Profile.Name;
    String bidId = profilePrefixMap.get(recentProfileName);
    bid.Bid_unique_label__c =  ((bidId == null) ? defaultPrefix : bidId);           
}
upsert recentBids;

此代码仍有一些问题。

  1. 您可能会在单个事务中达到不超过10K行插入/更新的限制(您至少应该添加LIMIT子句)。
  2. 您正在将触发器上下文中的数据与某些不相关的内容的数据修复混合在一起。你不应该“背驮式”,因为用户不会理解为什么他们会看到来自他们没有触及的数据的错误。
  3. 更不用说“最后修改过”在您的系统中现在毫无价值。
  4. 如果是清理坏数据的一次性活动(修复唯一标签) - 请考虑运行数据修复并删除此代码。如果它确实是一个反复出现的情况 - 写一个批处理作业。

    或者调查一下你是否可以编写一个工作流规则来生成唯一键,看起来它是可行的并且配置编码解决方案。