如何用Apex Trigger合并重复Lead?新手遇触发器报错求助
我是Salesforce新手,正在学习相关技术。需要实现:创建Lead记录时,通过LastName字段检测重复项,若存在重复则将新记录与已有记录合并,而非新建。编写了以下Trigger Handler和Trigger,但遇到错误,求解决方向。
编写的代码
LeadTriggerHandler类
public class LeadTriggerHandler { public static void duplicateMerge(){ List<Lead> leadList = [SELECT Id,Name, Email, Phone, FirstName, LastName FROM Lead]; List<Lead> leadTrigger = Trigger.new; for(Lead leadVarTrigger : leadTrigger){ for(Lead leadVar : leadList){ //System.debug(leadVar.LastName + '==' + leadVarTrigger.LastName); if(leadVarTrigger.LastName == leadVar.LastName) { //System.debug(leadVar.LastName + '==' + leadVarTrigger.LastName); //leadVarTrigger.addError('This is a duplicate record'); Database.merge(leadVar, leadVarTrigger); System.debug('Trigger Successful'); } } } } }
LeadTrigger触发器
trigger LeadTrigger on Lead (after insert) { if(Trigger.isafter && Trigger.isInsert) { LeadTriggerHandler.duplicateMerge(); } }
遇到的错误
使用After Insert触发器时的错误
LeadTrigger: execution of AfterInsert caused by: System.DmlException: Merge failed. First exception on row 0 with id 00Q5j00000ENUGVEA5; first error: INVALID_FIELD_FOR_INSERT_UPDATE, Unable to create/update fields: Name. Please check the security settings of this field and verify that it is read/write for your profile or permission set.: [Name] Class.LeadTriggerHandler.duplicateMerge: line 18, column 1 Trigger.LeadTrigger: line 5, column 1
使用Before Insert触发器时的错误
LeadTrigger: execution of BeforeInsert caused by: System.StringException: Invalid id at index 0: null External entry point Trigger.LeadTrigger: line 5, column 1
解决方向
错误原因分析
- Before Insert触发器报错:Before Insert阶段新创建的Lead还未生成Id,而
Database.merge()操作要求参与合并的记录必须有有效Id,因此触发"Invalid id"错误,不能在Before Insert阶段执行合并操作。 - After Insert触发器报错:Lead的Name字段是系统自动生成的只读字段(由FirstName和LastName拼接而成),合并操作中尝试修改该字段导致权限异常。同时当前代码存在逻辑缺陷:
- 全表查询所有Lead会引发严重性能问题
- 嵌套循环会导致重复合并(多个新Lead与多个已有Lead匹配时,多次执行merge)
- 未做递归控制,合并操作可能触发触发器循环执行
修正方案
- 固定触发器阶段:仅使用After Insert触发器,避免Before Insert的Id缺失问题。
- 优化查询逻辑:提取新记录的所有LastName,仅查询与这些LastName匹配的已有Lead(排除当前插入的记录),用Map构建LastName到已有Lead的映射,避免嵌套循环。
- 处理只读字段:合并操作时不手动设置Name字段,让系统自动处理字段合并逻辑。
- 添加递归控制:防止触发器因合并操作循环执行。
- 处理多重复场景:如果同一个LastName对应多个已有Lead,需指定合并目标(比如最新创建的记录),避免冲突。
修正后的示例代码
优化后的LeadTriggerHandler类
public class LeadTriggerHandler { public static void duplicateMerge(){ // 递归控制:避免合并操作触发的触发器再次执行此逻辑 if(Trigger.isRecursive) return; Set<String> lastNames = new Set<String>(); for(Lead newLead : Trigger.new){ if(String.isNotBlank(newLead.LastName)){ lastNames.add(newLead.LastName); } } // 查询已有Lead,排除当前插入的记录 Map<String, Lead> lastNameToExistingLead = new Map<String, Lead>(); for(Lead existingLead : [SELECT Id, LastName FROM Lead WHERE LastName IN :lastNames AND Id NOT IN :Trigger.newMap.keySet()]){ // 同一个LastName对应多个记录时,取最后一条(可根据业务需求调整) lastNameToExistingLead.put(existingLead.LastName, existingLead); } for(Lead newLead : Trigger.new){ Lead existingLead = lastNameToExistingLead.get(newLead.LastName); if(existingLead != null){ try{ // 合并新记录到已有记录,系统自动处理字段合并 Database.merge(existingLead, newLead); System.debug('合并成功:已有Lead Id=' + existingLead.Id + ',新Lead Id=' + newLead.Id); } catch(DmlException e){ System.debug('合并失败:' + e.getMessage()); newLead.addError('无法合并重复记录:' + e.getMessage()); } } } } }
调整后的LeadTrigger触发器
trigger LeadTrigger on Lead (after insert) { if(Trigger.isAfter && Trigger.isInsert){ LeadTriggerHandler.duplicateMerge(); } }
内容的提问来源于stack exchange,提问作者Sri Hari Rajan

