好,我们来看Apex里一个很实用的写法——SOQL for循环。你平常用SOQL查数据,可能习惯先查出来再循环。但Salesforce专门提供了两种直接在for循环里写SOQL的格式,用好了能让代码干净又高效。
第一种,单一的sObject格式。写法就是 `for(Account a : [SELECT ...])`,每次循环取一条记录。这很好理解,也最容易上手。但注意,如果你在循环体里做DML操作,比方说每次更新一条记录,那就会变成一条一条执行,数据一多,很容易碰到调控器限制,效率也很低。
所以就有了第二种,sObject列表格式。写法是 `for(List
accList : [SELECT ...])`,每次循环会拿到一个列表,这个列表里最多有200条记录。系统内部是一次取回200条,然后你可以在循环里对整个列表做批量处理,比如一次更新这200条,这样DML次数大大减少,特别适合批量操作。
举个例子,假设你只查出3条记录。用单一格式,循环体要执行3次;而用列表格式,因为3条都在一个批次里,循环体只执行1次,处理的是这3条记录组成的列表。数据量大的时候,优势就更明显了。
这两种格式背后,Apex其实会自动帮你处理分页,用内部的query和queryMore,所以你不用手动去翻页,而且还可以避免堆大小限制,因为一次只加载一批评记录到内存。不过它也可能会比先全查出来再循环多用一些CPU,这是因为它内部不断调用queryMore来获取下一批。总体还是利大于弊。
在循环控制上,你用`break`提前退出,或者`continue`跳过当前记录或当前批次,两种格式都正常工作,不用担心。
有一个特别容易踩的坑:如果你在一个for循环里访问大型子记录集——比如一个账户下面超过200个联系人,直接在循环体内用 `account.Contacts` 这种关系查询,很可能会触发 Analyst 异常(系统为了保护性能限制了这种嵌套查询的行数)。解决办法很简单,用嵌套的for循环:外层查出账户,内层单独写一个子记录的SOQL for循环来处理联系人,这样就不会触发限制。
所以简单记住,平时单一格式写起来快,但DML操作要注意;批量处理优先选列表格式。碰见子记录数量多的情况,就拆成嵌套循环,代码安全又好维护。好,这一节我们就先聊到这里。