Monday, August 9, 2021

Query for all the fields of an object in SOQL

We all might have come across scenarios where we want to query for all the fields of an object.  In SQL we use the symbol * to fetch all the fields, but unfortunately we do not have any such in SOQL.  SF recently came up with amazing new feature in Spring'21 where all the fields belonging to a single sObject can be queried.

We can now use the below keywords in our SOQL.

  • FIELDS(ALL) - Fetches all(including standard and custom) the fields of object.
  • FIELDS(STANDARD) - This fetches only the standard fields of the object.
  • FIELDS(Custom) - This fetches only the custom fields of the object.

For using the above Keywords, the pre-requisite is "LIMIT" keyword should be used with utmost value of "200".  This means that not more than 200 records can be fetched if any of the above mentioned keywords are present in the SOQL.  And also is not supported with an unbounded set of fields in this API

//Below query will fetch all the fields of the Account Object
SELECT FIELDS(ALL) FROM Account LIMIT 200

//Below query will fetch only the Standard fields of the Account Object
SELECT FIELDS(STANDARD) FROM Account LIMIT 200

//Below query will fetch only the custom fields of the Account Object
SELECT FIELDS(CUSTOM) FROM Account LIMIT 200
 PS: Above can be executed in "Query Editor" present inside Developer Console to check the results.  Only FIELDS(STANDARD) is made available to be used inside APEX.

Source : https://developer.salesforce.com/blogs/2021/01/new-soql-fields-function-is-ga

It is undoubtedly a wonderful feature but with the limitation of not fetching more than 200 records and not making it completely available in apex, it could not solve our purpose in all the scenarios.

To overcome this, let us make use of Dynamic SOQL to get all the fields of the record.  To make this generic enough, let's create a new static method which accepts object Name as String.   With the received objectName it will return a SOQL Query(String) that includes all the fields

public class Utils {
    public static String prepareSOQL(String sobjectName){
	String strSOQL = 'SELECT ';
	Map<String, Schema.SObjectField> fMap = Schema.getGlobalDescribe().get(sobjectName.toLowerCase()).getDescribe().Fields.getMap();
    
	for (Schema.SObjectField ft : fMap.values()){ 
		Schema.DescribeFieldResult fd = ft.getDescribe();
		if (fd.isUpdateable()){ // add field only if it is accessable
			strSOQL += fd.getName()+',';
		}
	}
	strSOQL = strSOQL.removeEnd(',');
	strSOQL += ' FROM '+sobjectName;
	return strSOQL;
    }
}

The above method accepts a string (objectName) and returns a SOQL Query of type string which includes all the fields and this can be invoked from any place when needed

//lstAcc will hold all the records with all the fields
String strSOQL = Utils.prepareSOQL('Account');
List<Account> lstAcc = Database.query(strSOQL);

If we use the approach of dynamic SOQL, we don't have to worry about the LIMIT clause, but remember to use this approach of querying for all the fields only when needed and also keep in thoughts that the SOQL Query length should not exceed more than 10K.


Tip : Usage of .keyset() is not supported in Dynamic SOQL.

Yes, you read it right.  We all tend to use Maps and have them part of our SOQL query.  But map.keyset() in a dynamic SOQL Query will not fetch the desired result.  You need to assign the map.keyset() to another set variable and use set in your SOQL.  It is because variables / collections can be used in dynamic SOQL, but not the methods.  


Hope you find it interesting.  Thank you for visiting and feedback is much appreciated!!! 


"....Bazingaa..."



5 comments:

  1. I would seriously question whether it is ever necessary to query for more than 200 fields. This has to be such a very special scenario where such a thing would be needed and it seems this leads developers to use this even when that is not needed. Seems like a dangerous thing to utilize, imho.

    ReplyDelete
    Replies
    1. LIMIT 200 applies for the records not for the fields..
      It is very common for an object to hold more than 200 records and given provision of SF will fail in such scenario.
      The alternative method mentioned in this post will help in such scenario of preparing the Soql dynamically

      Delete