1

I want to update records before insert if there is a match on a lookupkey rather than inserting a new record. I have viewed the related question but do not understand how to get the trigger list to update rather than insert a new record? I appreciate everyone taking the time to review, and help a new coder out.

Trigger:

trigger TINCheck on Account (before insert) {
    dupeCheck.checkforDupes(trigger.New);
}

Class:

//A Utility class to process Account records 
public class dupeCheck {

    //the AccountTINTrigger list is getting passed in by our trigger; this should match trigger.new
    public static void checkforDupes(List<Account> itemsFromTrigger){

        //list variable for our query to use as a limit/bind variable
        List<String> namesFromTrigger = new List<String>();
        //populate that list variable
        for(Account acct: itemsFromTrigger){
            namesFromTrigger.add(acct.LLC_BI__lookupKey__c);
        }

        //query for existing items, but only if they have the same TIN (WHERE cond)
        List<Account> existingRelationship = ([SELECT id, LLC_BI__lookupKey__c  FROM Account 
            WHERE LLC_BI__lookupKey__c in :namesFromTrigger]);

        List<account> Recordstoupdate = new List <Account>();
        //check to see if there are matches
        if(existingRelationship.size() > 0){
            //this means we have some dupes and we need to identify which records are dupes
            //loop through Accounts

            for (Account currentRelationship: existingRelationship){
                for(Account newRelationship: itemsFromTrigger){
                    if(currentRelationship.LLC_BI__lookupKey__c == newRelationship.LLC_BI__lookupKey__c) {
                        newRelationship.Id = currentRelationship.Id;}
//What else is needed here to update the itemsFromTrigger so that records are upserted rather than inserted?
                }
            }
        } 
    }
}
4
  • 1
    The parameter passing looks fine (consistent with Trigger Context Variables); what problem are you having?
    – Keith C
    Commented Sep 19, 2016 at 14:51
  • Hi Keith, I've added the error I am receiving to the question. Thanks so much for taking the time to look at this. Commented Sep 19, 2016 at 15:01
  • 2 points. 1 you are making dml in for loop. 2. In before trigger you are making dml on same record. One bonus is I don't think your logic is correct. Commented Sep 19, 2016 at 15:20
  • Hi Tushar, I have moved the upsert outside of the loop. Commented Sep 19, 2016 at 15:37

2 Answers 2

1

I agree with the duplicate vote here...but I won't badge hammer just yet. The correct solution here is to call Database.delete(duplicateIds). The steps should be:

  1. Identify duplicates
  2. Update existing records
  3. Delete inserted records

Something like:

static Map<String, Account> getExistingDuplicates(List<Account> records)
{
    Set<String> keys = new Set<String>();
    for (Account record : record) keys.add(record. LLC_BI__lookupKey__c);

    Map<String, Account> existing = new Map<String, Account>();
    for (Account record : [
        SELECT LLC_BI__lookupKey__c FROM Account WHERE LLC_BI__lookupKey__c IN :keys
    ]) existing.put(record.LLC_BI__lookupKey__c, record);
    return existing;
}
public static void deduplicate(List<Account> records)
{
    List<Id> duplicateIds = new List<Id>();
    Map<String, Account> existing = getExistingDuplicates(records);
    for (Account record : records)
    {
        String key = record.LLC_BI__lookupKey__c;
        if (existing.containsKey(key))
        {
            duplicateIds.add(record.Id);
            Account clone = record.clone();
            clone.Id = existing.get(key).Id;
            existing.put(key, clone);
        }
    }
    update existing.values();
    Database.delete(duplicateIds);
    // error handling and transaction control recommended
}
3
  • This is a before insert trigger, so I guess I don't understand how the above after insert context applies? I want to understand, and appreciate the input. Perhaps I am looking at the whole problem incorrectly. I want to update records on insert, based on the lookup key rather than inserting a new record. Commented Sep 19, 2016 at 17:11
  • 1
    That's part of my point, you should be looking to implement this functionality after insert.
    – Adrian Larson
    Commented Sep 19, 2016 at 17:31
  • So could you clarify a little more. The method would be to insert the new record, reassign all non-null fields of the original record to the newly inserted values of the new record, and then delete the new record? Commented Sep 19, 2016 at 17:36
0

(wanted to post this as a comment) 2 things to say

  1. Use the Maps instead of the nested for loops
  2. I see that you are trying to update the "Id" of the values from Trigger.New which is not the right thing to do, and causing the error.

PS, ID is a system field.

2
  • Thanks, I will re-write using maps, instead of loops. I think your second point is my bigger problem. Do you have some suggestions on how to upsert based on the lookup rather than insert? Commented Sep 19, 2016 at 17:25
  • A dirty trick. 1. Use a new list for upsert. 2. Use adderror for the values in "itemsFromTrigger" inorder not to save them. (But beware of recursive loop u'll be getting into)
    – blackwind
    Commented Sep 19, 2016 at 17:36

Not the answer you're looking for? Browse other questions tagged .