0

I have below query string in an apex batch class that throw error. Can some one please help?

Error

Unexpected token '{'

Query String

  String query = 'SELECT Call_Duration_Required_abv__c,Id FROM Account where Call_Duration_Required_abv__c=false and IsPersonAccount=True and Id in (Select Account_vod__c from Address_vod__c where inactive_vod__c = false and Zip_vod__c in :'+zipSet+')';

Apex Batch class

global class ABV_CallDuration implements Database.Batchable<sObject> {
    global Database.QueryLocator start(Database.BatchableContext BC) {
          Set<String> zipSet = new Set<String>();
        for(Call_Duration_Zip_Code_abv__c c: [Select id, Zip_Codes_abv__c from Call_Duration_Zip_Code_abv__c]) {
                zipSet.add(c.Zip_Codes_abv__c);
            } 

        String query = 'SELECT Call_Duration_Required_abv__c,Id FROM Account where Call_Duration_Required_abv__c=false and IsPersonAccount=True and Id in (Select Account_vod__c from Address_vod__c where inactive_vod__c = false and Zip_vod__c in :'+zipSet+')';
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<Account> scope) {

         for(Account ac : scope )
         {
           if(ac.Call_Duration_Required_abv__c==false)
           ac.Call_Duration_Required_abv__c=true;
         }
         update scope;
    }   

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

There is no need to use dynamic SOQL in batch Apex (unless you have to). Because if you will do typo, and SOQL would be invalid, you will not see error message after code complying (saving to org).

String query = 'SELECT Call_Duration_Required_abv__c,Id FROM Account where Call_Duration_Required_abv__c=false and IsPersonAccount=True and Id in (Select Account_vod__c from Address_vod__c where inactive_vod__c = false and Zip_vod__c in :'+zipSet+')';
                return Database.getQueryLocator(query);

There is a signature that accepts a list of SObjects as well as one that accepts a (SOQL) string. Replace above lines with the following:

return Database.getQueryLocator([
    select Call_Duration_Required_abv__c, Id
    from Account
    where Call_Duration_Required_abv__c=false
        and IsPersonAccount=True
        and Id in (
            select Account_vod__c
            from Address_vod__c
            where inactive_vod__c = false
                and Zip_vod__c in :zipSet
                  )
    ]
);
5
  • It is giving no error now but the update is not happening – Testing_SFDC Jun 8 '17 at 12:37
  • did you double check, that all your queries (zipSet) are returning expected values in SOQL Query Editor too ? – Oleksandr Berehovskyi Jun 8 '17 at 12:40
  • Yes it's fine in debug log – Testing_SFDC Jun 8 '17 at 12:42
  • Can you please put the change in entire of batch class please – Testing_SFDC Jun 8 '17 at 12:42
  • Query getting truncated and returns 0 records in scope – Testing_SFDC Jun 8 '17 at 12:47
2

The reason for the error itself is that if you use string coercion to add a collection to the query it outputs as {...}. In other words:

system.debug('' + new Set<String>{'A', 'B'}); // yields {A, B}

If you want to include a set in your query, simply merge in the variable:

String query = '...Zip_vod__c IN :zipSet';

If you want to use literal values, you would need to more work, wrapping each value in escaped quotes, joining the collection with a comma, then wrapping that output with parentheses. Make sure you remove the leading colon character if you take this approach.

List<String> queryValues = new List<String>();
for (String zip : zipSet) queryValues.add('\'' + String.escapeSingelQuotes(zip) + '\'');
String querySet = '(' + String.join(queryValues, ',') + ')';
String query = '...Zip_vod__c IN ' + querySet;

As mentioned in the other answer, however, static queries are far preferable. You should never use a dynamic query unless you want to achieve something which is impossible to support statically.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.