function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
HamptonHampton 

Apex Code to Delete Records

Hello:

 

I do a monthly Upsert via bulk upload (Apex Data Loader) of records on custom object Subscriber__c.

 

What I want to do is once the upsert is complete, delete any records that were not created or updated during he bulk Upsert process.

 

Here is the trigger I have written - and I am aware this may be terrible or not even close to what I need :)

 

trigger DeleteSubs on Subscriber__c(after insert, after update) {
 List<Id> lstId = new List<Id>();
 
for(Subscriber__c sub: Trigger.old){
        List<Subscriber__c> nolongersubs = [Select Id from Subscriber__c where LastModifiedDate<TODAY];
        delete nolongersubs;
    }
 
}

 When trying to insert a single record I am getting execution of AfterInsert caused by: System.NullPointerException: Attempt to de-reference a null object:Trigger.DeleteSubs: line 4, column 1

 

Any help would be greatly appeciated.

 

Thanks,

 

Hampton

 

 

Best Answer chosen by Admin (Salesforce Developers) 
Jerun JoseJerun Jose

Ahh.. The class R3S_ClientExpScheduler has been written as an inner class to the deleteSubscribers one. Move it out and have that as a seperate new class.

For better name lets call it deleteSubscribersScheduled.

Once you have this class created, you can now select deleteSubscribersScheduled from the schedule apex page.

 

To summarize, have TWO seperate classes.

 

global class deleteSubscribers implements Database.Batchable<sObject>{
    global final String Query;
    global deleteSubscribers(String q){
        Query=q;
    }

    global Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC,List<Subscriber__c> scope){
        delete scope;
    }

    global void finish(Database.BatchableContext BC){}
}

 and another one

 

global class deleteSubscribersScheduled implements Schedulable{
    global void execute(SchedulableContext sc){
        String query = 'select id from Subscriber__c where LastModifiedDate != LAST_N_DAYS:30';
        deleteSubscribers delBatch = new deleteSubscribers(query);
        Id BatchProcessId = Database.ExecuteBatch(delBatch);
    }
}

 

All Answers

hitzhitz

HI Hampton,

 

I dont think this is possible using Trigger. This is possible using Batch class. Create Schedulble Batch class which deletes accounts as per your last modified date criteria and schedule your batch class monthly.

HamptonHampton

Thanks for the reply. So if I use this somewhat standard Batch Class, where do I put the qualifier if I want to delete all records with a LastModifiedDate more than 30 days ago?

 

global class deleteSubscribers implements Database.Batchable
{
global final String Query;
global deleteSubscribers(String q)
{
Query=q;
}

global Database.QueryLocator start(Database.BatchableContext BC)
{
return Database.getQueryLocator(query);
}

global void execute(Database.BatchableContext BC,List scope)
{
List <Subscriber__c> Subscriber = new list<Subscriber>();
for(Subscriber__c s : scope)
{
Subscriber__c su = (Subscriber__c)s;
Subscriber.add(su);
}
Delete lstAccount;
}

global void finish(Database.BatchableContext BC)
}

 Thanks again!

Jerun JoseJerun Jose

You will need a batch apex as well as a schedulable apex class

 

Batch apex: This will just delete all the records that are being passed to it.

 

global class deleteSubscribers implements Database.Batchable<Subscriber__c>{
	global final String Query;
	global deleteSubscribers(String q){
		Query=q;
	}

	global Database.QueryLocator start(Database.BatchableContext BC){
		return Database.getQueryLocator(query);
	}

	global void execute(Database.BatchableContext BC,List<Subscriber__c> scope){
		delete scope;
	}

	global void finish(Database.BatchableContext BC){}
}

 Schedulable apex: This will query for the records to be deleted and pass that to the batch apex.

 

global class R3S_ClientExpScheduler implements Schedulable{
    global void execute(SchedulableContext sc){
		String query = 'select id from Subscriber__c where LastModifiedDate != LAST_N_DAYS:30';
        deleteSubscribers delBatch = new deleteSubscribers(query);
        Id BatchProcessId = Database.ExecuteBatch(delBatch);
    }
}

 

HamptonHampton

I got the class to save but am getting an error when I try to schedule it :

 

Error: You must select an Apex class that implements the Schedulable interface.

 

Thoughts?

 

Hampton

Jerun JoseJerun Jose
You will have to schedule the schedulable apex class.

In the example I gave above, you will need to select the R3S_ClientExpScheduler class.

If you still cannot select it, then check the Valid checkbox on the class detail page. If it is unchecked, then edit and save the class again.

If the valid checkbox is checked and still you cannot select the class in the scheduler page, then try renaming the apex class to something else. I know it sounds weird, but I have had this problem in the past.
HamptonHampton

I guess I am confused, a lot of this is over my head and I am trying to learn as I go. When I go to schedule the class, deleteSubscribers is the only class listed as availble to schedule. I don't have a class R3S_ClientExpScheduler. I guess that is what my problem is?

 

I am very novice when it comes to Apex. I can write very simple codes for field updates and such but that is about it. Apologies in advance for my lack of knowledge.

 

Hampton

Jerun JoseJerun Jose
No worries. Could you post the code for the batch apex and the scheduled apex classes that you have saved in your org. I believe there is a small confusion.
HamptonHampton
global class deleteSubscribers implements Database.Batchable<sObject>{
    global final String Query;
    global deleteSubscribers(String q){
        Query=q;
    }

    global Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC,List<Subscriber__c> scope){
        delete scope;
    }

    global void finish(Database.BatchableContext BC){}
    
    global class R3S_ClientExpScheduler implements Schedulable{
    global void execute(SchedulableContext sc){
        String query = 'select id from Subscriber__c where LastModifiedDate != LAST_N_DAYS:30';
        deleteSubscribers delBatch = new deleteSubscribers(query);
        Id BatchProcessId = Database.ExecuteBatch(delBatch);
    }
}
}

 I pieced this together form an earlir reponse to the post. I am usually pretty good at understanding code once I can get some help getting it to work so thank you again for the help!

 

Hampton

Jerun JoseJerun Jose

Ahh.. The class R3S_ClientExpScheduler has been written as an inner class to the deleteSubscribers one. Move it out and have that as a seperate new class.

For better name lets call it deleteSubscribersScheduled.

Once you have this class created, you can now select deleteSubscribersScheduled from the schedule apex page.

 

To summarize, have TWO seperate classes.

 

global class deleteSubscribers implements Database.Batchable<sObject>{
    global final String Query;
    global deleteSubscribers(String q){
        Query=q;
    }

    global Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC,List<Subscriber__c> scope){
        delete scope;
    }

    global void finish(Database.BatchableContext BC){}
}

 and another one

 

global class deleteSubscribersScheduled implements Schedulable{
    global void execute(SchedulableContext sc){
        String query = 'select id from Subscriber__c where LastModifiedDate != LAST_N_DAYS:30';
        deleteSubscribers delBatch = new deleteSubscribers(query);
        Id BatchProcessId = Database.ExecuteBatch(delBatch);
    }
}

 

This was selected as the best answer
Bhawani SharmaBhawani Sharma

Create batch class and Schedule class separately. Curently you created Scheduler inside the batch

 

global class deleteSubscribers implements Database.Batchable<sObject>{
    global final String Query;
    global deleteSubscribers(String q){
        Query=q;
    }

    global Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC,List<Subscriber__c> scope){
        delete scope;
    }

    global void finish(Database.BatchableContext BC){}
}

 

 

global class R3S_ClientExpScheduler implements Schedulable{
    global void execute(SchedulableContext sc){
        String query = 'select id from Subscriber__c where LastModifiedDate != LAST_N_DAYS:30';
        deleteSubscribers delBatch = new deleteSubscribers(query);
        Id BatchProcessId = Database.ExecuteBatch(delBatch);
    }
}

 

HamptonHampton

Got it...thank you very much for your help.

vinod reddy 21vinod reddy 21
Hi,

Anybody have Test Class for above code.

Thanks in advance
Vipul-GoyalVipul-Goyal
Hey,
I just built a Library to delete bulk records in apex.
You can delete them in user or system mode in a batch size that suits you.
There are a host of other features too.
To use the library you can go to : https://github.com/vipul-goyal/Salesforce-Batch-To-Delete-Records
The code is in DX format.

Please star the repository if you find it worth it.

Thanks