Newer Version Available

This content describes an older version of this product. View Latest

Dynamic SOQL

Dynamic SOQL refers to the creation of a SOQL string at run time with Apex code. Dynamic SOQL enables you to create more flexible applications. For example, you can create a search based on input from an end user or update records with varying field names.

To create a dynamic SOQL query at run time, use the Database.query or Database.queryWithBinds methods, in one of the following ways.

  • Return a single sObject when the query returns a single record:
  • Return a list of sObjects when the query returns more than a single record:
  • Return a list of sObjects using a map of bind variables:

The Database.query and Database.queryWithBinds methods can be used wherever an inline SOQL query can be used, such as in regular assignment statements and for loops. The results are processed in much the same way as static SOQL queries are processed.

With API version 55.0 and later, as part of the User Mode for Database Operations feature, use the accessLevel parameter to run the query operation in user or system mode. The accessLevel parameter specifies whether the method runs in system mode (AccessLevel.SYSTEM_MODE) or user mode (AccessLevel.USER_MODE). In system mode, the object and field-level permissions of the current user are ignored, and the record sharing rules are controlled by the class sharing keywords. In user mode, the object permissions, field-level security, and sharing rules of the current user are enforced. System mode is the default.

Dynamic SOQL results can be specified as concrete sObjects, such as Account or MyCustomObject__c, or as the generic sObject data type. At run time, the system validates that the type of the query matches the declared type of the variable. If the query doesn’t return the correct sObject type, a run-time error is thrown. Therefore, you don’t have to cast from a generic sObject to a concrete sObject.

Dynamic SOQL queries have the same governor limits as static queries. For more information on governor limits, see Execution Governors and Limits.

For a full description of SOQL query syntax, see Salesforce Object Query Language (SOQL) in the SOQL and SOSL Reference.

Dynamic SOQL Considerations

You can use simple bind variables in dynamic SOQL query strings when using Database.query. The following is allowed:
However, unlike inline SOQL, you can’t use bind variable fields in the query string with Database.query. The following example isn’t supported and results in a Variable does not exist error.
You can instead resolve the variable field into a string and use the string in your dynamic SOQL query:

(API version 57.0 and later) Another option is to use the Database.queryWithBinds method. With this method, bind variables in the query are resolved from a Map parameter directly with a key, rather than from Apex code variables. This removes the need for the variables to be in scope when the query is executed. This example shows a SOQL query that uses a bind variable for an Account name; its value is passed in with the acctBinds Map.

SOQL Injection

SOQL injection is a technique by which a user causes your application to execute database methods you didn’t intend by passing SOQL statements into your code. This can occur in Apex code whenever your application relies on end-user input to construct a dynamic SOQL statement and you don’t handle the input properly.

To prevent SOQL injection, use the escapeSingleQuotes method. This method adds the escape character (\) to all single quotation marks in a string that is passed in from a user. The method ensures that all single quotation marks are treated as enclosing strings, instead of database commands.

Additional Dynamic SOQL Methods

The Dynamic SOQL examples in this topic show how to use the Database.query and Database.queryWithBinds methods. These methods also use Dynamic SOQL:

  • Database.countQuery and Database.countQueryWithBinds: Return the number of records that a dynamic SOQL query would return when executed.
  • Database.getQueryLocator and Database.getQueryLocatorWithBinds: Create a QueryLocator object used in batch Apex or Visualforce.