【问题标题】:Salesforce: System.LimitException: Too many SOQL queries: 101Salesforce:System.LimitException:SOQL 查询太多:101
【发布时间】:2013-02-12 08:07:30
【问题描述】:

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

我突然收到这个错误信息:

错误:无效数据。 查看以下所有错误消息以更正您的数据。
Apex 触发器 generateUniqueBidId 导致意外异常,请联系您的管理员: generateUniqueBidId: System.LimitException: Too many SOQL queries: 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);
    }

}

【问题讨论】:

    标签: salesforce force.com soql


    【解决方案1】:

    您在循环中有一个 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. 更不用说“最后修改者”现在在您的系统中毫无价值了。

    如果清理不良数据(修复唯一标签)是一次性活动,请考虑运行数据修复并删除此代码。如果它真的是一个反复出现的情况 - 编写一个批处理作业。

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

    【讨论】:

    • 这暂时解决了错误消息。我现在将继续使用代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-27
    • 1970-01-01
    • 2011-07-09
    • 1970-01-01
    • 1970-01-01
    • 2020-02-14
    • 2013-06-10
    相关资源
    最近更新 更多