Update all records using TouchRecords

 In admin, apex, developer, Salesforce, tips & tricks

Done well, Salesforce data takes care of itself.  Say you’ve got a process that updates a thing whenever the record is edited. Or maybe after a record is saved something else needs to happen.  Salesforce is great at making that happen.

But, and it’s a big one, let’s say you’ve just updated your process or added a new one and every record will correct itself once it’s edited.  How do you push all records to update so they adopt your new whatever and remain current?

This is where TouchRecords comes in.

TouchRecords is a simple Batch Apex routine that just saves, in geek-speak touches, every record you tell it to.

Why use batch apex?  Salesforce has its governor limits which prevent code from hogging or even crashing the servers. These limits limit the number of records you can update at once and the processing time you can use.  Batch Apex helps you live within the limits by processing data in bite-sized chunks, or batches.

If you have a lot complex code, workflow rules, visual flows you might need to limit the number of records in each batch.  This is especially true if you have a lot of Process Builder scripts in your org.  Thankfully, TouchRecords allows for controlling your batch size as well.

(Yeah, you’ll need to understand how to use sandboxes and deploy code, it’s apex after all, but still it’s not hard.  A basic understanding of SOQL is also needed.)


Let’s say you want all Account records to update themselves.

String Query = ‘Select ID From Account’;  
// Use a SOQL query to indicate the records to update.  Notice that only the ID field is needed.

Integer batchSize = 25;  
// Set to the size you need or use zero to leave it to the system default batch size of 200. 

TouchRecords.Start(Query, batchSize);

Here’s the code:

global class touchRecords implements Database.Batchable<sObject> {
    String myQuery;

    global touchRecords(string q ) {
        myQuery = q;

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

    global void execute(Database.BatchableContext BC, List<sObject> scope) {
            update scope;
        } catch (DmlException e) {
            system.debug('BATCH touchRecords error <<< ---------- \n');
            system.debug('Query: '+ myQuery);
            system.debug('Error: '+ e);

    global void finish(Database.BatchableContext BC) {
        // none needed

    global static void start(string q, integer batchsize){
        if (batchsize == null || batchsize == 0) batchsize = 200; // 200 is system default
        Database.executeBatch (new touchRecords(q), batchSize);

The test code is amazingly simple but gives 100% coverage.

private class touchRecords {
    @isTest static void test_touchRecords() {
        insert new account(name='test');
        string q = 'select id from account';
        touchRecords.start(q, null);

Leave a Comment