0

I am creating a before insert trigger. This trigger will handle records being inserted and that part works correctly, however I am having problems with records I want to flag for deleting.

In this case there would already be a record in Salesforce that would be flagged with 'A', now a update to that record is coming in with 'X' and that is a flag to me that I want to delete that record. The below gets me to the point of updating the record from 'A' to 'X', but I am stuck on how I can get these records deleted. The delete statement always returns 0 records. I assume I am doing this wrong or in the wrong place. Any ideas?

trigger enrollTrigger on hed__Program_Enrollment__c (before insert) {
Set<String> toBeDeleted= new Set<String>();

for(hed__Program_Enrollment__c myEnroll: trigger.New) {
   if(myEnroll.flag == 'X') {
    // Flag this for delete
     toBeDeleted.add(myEnroll.id);
    }  else {
   // process the records to insert
   }

   delete [SELECT ID, NAME FROM hed__Program_Enrollment__c in : toBeDeleted];
   }

Just adding some more context. Basically this would be done in bulk from the data loader as an upsert. Some records are brand new and I want to insert them. Other records were good before and marked with 'A' and now they have been flagged with an 'X' so I would want to remove that current 'A' record.

4
  • 1
    In before trigger there is no id assigned to record.Moreover you can't delete record in before insert as record is not even inserted yet
    – Elijah
    Commented Apr 7, 2022 at 17:56
  • @Elijah so would I need a separate process to delete these records then?
    – MarkC5000
    Commented Apr 7, 2022 at 17:59
  • What I understood is, you want to delete the record once its updated to value 'X' , your best bet would be to use after update.
    – Elijah
    Commented Apr 7, 2022 at 18:06
  • Seems like I should have posted my first comment as answer.
    – Elijah
    Commented Apr 7, 2022 at 18:09

2 Answers 2

3

You can't delete records before they're saved to the database (for lack of a better word), and that doesn't happen until just before an after insert trigger would fire.

Records being inserted are also not able to be queried until they are assigned an Id (which also happens just before an after insert trigger would fire).

If you're looking to handle situations where people are entering these records one at a time, then a validation rule would be a much better choice (stop bad data before it gets saved!).

If you're inserting these records from some other trigger or apex class, then you should be preventing the records you'd end up deleting from even attempting to be inserted in the first place.

e.g.

List<hed__Program_Enrollment__c> recordsToInsert = new List<hed__Program_Enrollment__c>();
for(SomeObject__c someRecord :[SELECT <some fields> FROM SomeObject__c WHERE <filters>]){
    hed__Program_Enrollment__c enrollment = createEnrollment(someRecord);

    if(enrollment.Flag__c = 'X'){
        // skip this record, and move on to the next iteration of the loop
        continue;
    }

    recordsToInsert.add(enrollment);
}

insert recordsToInsert;

+edit:

On a second reading, it seems like your records do not initially have this flag set to 'X', but that's happening in a separate update (through some process).

If that's the case, then you'd want to use the after update context to your trigger (you really should be using a trigger framework, but that's out of scope for your question), iterating through a trigger context variable to figure out which records should be deleted (adding them to a list), and then deleting them (no queries required).

Given your current trigger structure, such a trigger could look like

// Best practice is to have only a single trigger on any given object
// A single trigger can be run in different contexts by adding multiple contexts
//   inside the "()", separated with commas
trigger MyTrigger on MyObject__c (before insert, after update){
    // You can do specific work in each context by checking
    //   - Trigger.isBefore
    //   - Trigger.isAfter
    //   - Trigger.isInsert (or isUpdate, isDelete, isUndelete)
    //   - Trigger.operationType

    // Best practice is also to use a trigger framework and keep logic outside
    //   of the trigger itself.
    // I'm not going to go over that, but breaking your work into specific events
    //   like this will make that transition easier/more intuitive
    switch on Trigger.operationType{
        when System.TriggerOperation.BEFORE_INSERT{
            // do work to modify data before it's inserted so you can
            //   avoid needing to do a DML update
        }
        when System.TriggerOperation.AFTER_UPDATE{
            List<SObject> recordsToDelete = new List<SObject>();

            for(MyObject__c myRecord :trigger.new){
                if(myRecord.Flag__c == 'X'){
                    recordsToDelete.add(myRecord);
                }
            }

            delete recordsToDelete;
        }
    }
}
2
  • basically this would happen in bulk from the data loader on an upsert. There could be brand new records which I want to be inserted or there could be a change to a good record that is marked with 'A' and it's now 'X'. I would want to now delete that record as I no longer need it
    – MarkC5000
    Commented Apr 7, 2022 at 18:23
  • thanks this is what I was looking for.
    – MarkC5000
    Commented Apr 7, 2022 at 19:28
1

You can't delete a record before it's been inserted. However, you can delete the record after it's been inserted. Using after insert instead of before insert will allow you to immediately delete the record if you desire. This is a pretty common technique when you don't want to return an error yet also don't want to keep the record.

5
  • Although deleting is allowed in after insert but it doesn't make sense, why would someone want to delete record right after its inserted
    – Elijah
    Commented Apr 7, 2022 at 18:03
  • @sfdcfox so I should change the trigger to after insert? Would this still process the new records I am currently inserting that I don't want deleted?
    – MarkC5000
    Commented Apr 7, 2022 at 18:09
  • 1
    @Elijah Using addError may cause the entire transaction to fail (particularly when allOrNone=true, and you cannot alter the client setting this flag), so delete-after-insert is useful in those situations. Sometimes, you also can't even tell if the record should be deleted until after it's saved. That's just how it goes sometimes.
    – sfdcfox
    Commented Apr 7, 2022 at 18:15
  • 1
    @MarkC5000 Yes, using after insert would allow your deletion to go through.
    – sfdcfox
    Commented Apr 7, 2022 at 18:16
  • @sfdcfox Just adding some more context. Basically this would be done in bulk from the data loader as an upsert. Some records are brand new and I want to insert them. Other records were good before and marked with 'A' and now they have been flagged with an 'X' so I would want to remove that current 'A' record.
    – MarkC5000
    Commented Apr 7, 2022 at 18:25

You must log in to answer this question.

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