Difference between Static SOQL and Dynamic SOQL in Salesforce Apex

Salesforce Object Query Language, usually written as SOQL, is used in Apex to read records from Salesforce objects. The main difference between static SOQL and dynamic SOQL is when the query is defined. A static SOQL query is written directly in Apex between square brackets, while a dynamic SOQL query is built as a string at run time and executed with Database.query().

In most Apex classes, static SOQL should be the first choice because it is easier to read and Salesforce can validate the object names, field names, and query syntax earlier. Dynamic SOQL is useful when the selected fields, object name, filter conditions, or sort order must change based on user input, configuration, or reusable framework logic.

Static SOQL vs Dynamic SOQL quick comparison

Point of differenceStatic SOQLDynamic SOQL
How the query is writtenWritten directly inside square brackets in Apex.Built as a string and passed to Database.query().
Best use caseKnown object, known fields, and known filter structure.Object, fields, filters, or ordering must be decided at run time.
ReadabilityUsually easier to read and maintain.Can become hard to maintain if string building is not organized.
ValidationSalesforce can validate the query structure more directly.Some errors are found only when the dynamic query executes.
Security concernSafer by default when bind variables are used correctly.Needs careful input handling to avoid SOQL injection.

Static SOQL statements in Apex

A static SOQL query is written directly in Apex using square brackets. It is suitable when the object name, field names, and main filter logic are already known while writing the code. Static SOQL is commonly used in triggers, controllers, batch Apex, queueable classes, and service classes where the query structure does not need to change.

Static SOQL can still use Apex variables through bind variables. That means the query can accept changing values such as an Account Id or Last Name without making the query itself dynamic.

</>
Copy
Contact[] contacts = [SELECT testfield__C, FirstName, LastName FROM Contact WHERE LastName = 'Prasanth'];

In practical Apex code, it is usually better to query the Id field also and use a bind variable instead of hard-coding the filter value.

</>
Copy
String contactLastName = 'Prasanth';

List<Contact> contacts = [
    SELECT Id, FirstName, LastName, Email
    FROM Contact
    WHERE LastName = :contactLastName
];

When to use static SOQL in Salesforce Apex

  • Use static SOQL when the Salesforce object is known, such as Account, Contact, or a specific custom object.
  • Use it when the selected fields are fixed in the Apex logic.
  • Use it when only filter values change, because bind variables can handle changing values.
  • Use it when readability and maintainability are more important than query flexibility.

Dynamic SOQL in Apex

Dynamic SOQL refers to the creation of a SOQL query 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, choose fields from configuration, or query different objects from reusable code. This is the major difference between static SOQL and dynamic SOQL.

  • Dynamic SOQL helps when the query structure is not completely known until the code runs.
  • To create a dynamic SOQL query at run time, use the Database.query() method.
  • Dynamic SOQL should be written carefully because string concatenation can create syntax errors or security issues if user input is not handled properly.

To create Dynamic SOQL query at run time, use the database query method as shown below.

</>
Copy
List<sObject> sObject = Database.query(string);

The following example builds the field list and filter dynamically, then executes the query with Database.query().

</>
Copy
String objectName = 'Contact';
String fieldList = 'Id, FirstName, LastName, Email';
String lastNameValue = 'Prasanth';

String queryString = 'SELECT ' + fieldList +
    ' FROM ' + objectName +
    ' WHERE LastName = :lastNameValue';

List<sObject> records = Database.query(queryString);

When to use dynamic SOQL in Salesforce Apex

  • Use dynamic SOQL when the object name is selected at run time.
  • Use it when the list of fields comes from custom metadata, field sets, or admin configuration.
  • Use it when filters are optional and the final WHERE clause must be assembled based on available values.
  • Use it for generic search screens where users can choose fields, filters, or sort order.
  • Use it in reusable framework code that must work across multiple Salesforce objects.

Static SOQL bind variables are often enough

A common mistake is using dynamic SOQL only because the filter value changes. A changing value does not require dynamic SOQL. Static SOQL supports bind variables, and that is usually cleaner.

</>
Copy
Id accountIdValue = '001000000000000AAA';

List<Contact> contacts = [
    SELECT Id, FirstName, LastName
    FROM Contact
    WHERE AccountId = :accountIdValue
];

In this example, only the value of accountIdValue changes. The object name, selected fields, and filter structure are fixed, so static SOQL is the better option.

Dynamic SOQL syntax with Database.query()

The general syntax for dynamic SOQL is to store the query in a string and pass that string to Database.query(). The return type is usually List<sObject> when the object type is not known at compile time.

</>
Copy
String queryString = 'SELECT fieldNames FROM ObjectName WHERE condition';
List<sObject> records = Database.query(queryString);

If the object is known, you can cast the result to a specific sObject list only when the query actually returns that object type.

</>
Copy
String queryString = 'SELECT Id, Name FROM Account LIMIT 10';
List<Account> accounts = Database.query(queryString);

SOQL injection risk in dynamic SOQL

Dynamic SOQL must be written carefully when any part of the query depends on user input. If user input is directly joined into the query string, the final SOQL statement may not behave as intended. Prefer bind variables for values and validate any dynamic object names, field names, and sort directions before adding them to the query.

For string values that must be concatenated, use String.escapeSingleQuotes(). However, escaping is not a replacement for checking whether a field or object is actually allowed in your Apex logic.

</>
Copy
String userSearchText = 'Prasanth';
String safeSearchText = String.escapeSingleQuotes(userSearchText);

String queryString = 'SELECT Id, FirstName, LastName ' +
    'FROM Contact ' +
    'WHERE LastName = \'' + safeSearchText + '\'';

List<Contact> contacts = Database.query(queryString);

When possible, use bind variables in dynamic SOQL for filter values. This keeps values separate from the query structure.

</>
Copy
String lastNameValue = 'Prasanth';
String queryString = 'SELECT Id, FirstName, LastName FROM Contact WHERE LastName = :lastNameValue';

List<Contact> contacts = Database.query(queryString);

Choosing between static SOQL and dynamic SOQL

Use this simple decision rule: if only the values change, use static SOQL with bind variables. If the query structure changes, use dynamic SOQL. Query structure means the object, fields, conditions, grouping, ordering, or limit clauses are assembled at run time.

RequirementRecommended SOQL typeReason
Find Contacts for a known Account IdStatic SOQLThe object and fields are fixed; only the value changes.
Let users choose search filters on a custom search pageDynamic SOQLThe WHERE clause may change at run time.
Query fields selected from a field setDynamic SOQLThe field list is not fixed in the Apex code.
Read Accounts with a fixed status filterStatic SOQLThe query is predictable and easier to validate.
Build a generic export tool for multiple objectsDynamic SOQLThe object and fields may vary by request.

Governor limit reminder for both static and dynamic SOQL

Static SOQL and dynamic SOQL both run under the same Apex governor limits. Dynamic SOQL does not avoid SOQL query limits, row limits, or CPU time limits. Avoid placing either type of SOQL query inside a loop. Collect record Ids first, then run one query outside the loop whenever possible.

</>
Copy
Set<Id> accountIds = new Set<Id>();

for (Contact con : Trigger.new) {
    if (con.AccountId != null) {
        accountIds.add(con.AccountId);
    }
}

List<Account> accounts = [
    SELECT Id, Name
    FROM Account
    WHERE Id IN :accountIds
];

Common mistakes with static and dynamic SOQL

  • Using dynamic SOQL for simple variable values: Use static SOQL with bind variables when only the value changes.
  • Hard-coding user input into a dynamic query: Validate or escape user-provided values before using them in a query string.
  • Forgetting spaces while concatenating query strings: Missing spaces can produce invalid SOQL such as ContactWHERE.
  • Querying fields the running user cannot access: Review object-level and field-level security requirements for your use case.
  • Putting SOQL inside loops: Both static and dynamic SOQL count against governor limits.

Official Salesforce references for SOQL in Apex

For complete syntax details, refer to the Salesforce documentation for Dynamic SOQL, SOQL queries in Apex, and Apex governor limits.

FAQ on static SOQL and dynamic SOQL

What is the difference between static SOQL and dynamic SOQL?

Static SOQL is written directly inside square brackets in Apex. Dynamic SOQL is built as a string at run time and executed with Database.query(). Static SOQL is better when the query structure is fixed, while dynamic SOQL is used when the object, fields, filters, or sorting need to change at run time.

Should I use dynamic SOQL when only the filter value changes?

No. If only the filter value changes, use static SOQL with a bind variable. Dynamic SOQL is normally needed only when the query structure itself changes.

Which is safer: static SOQL or dynamic SOQL?

Static SOQL is generally safer and easier to maintain because the query is written directly in Apex. Dynamic SOQL can also be safe, but user input must be validated or escaped, and bind variables should be used for values whenever possible.

Does dynamic SOQL avoid Salesforce governor limits?

No. Static SOQL and dynamic SOQL both follow the same Apex governor limits. Dynamic SOQL does not allow unlimited queries or unlimited rows.

Can dynamic SOQL return a strongly typed list?

Yes, if the query returns a known object type. For example, a dynamic query on Account can be assigned to List<Account>. If the object type is not known, use List<sObject>.

Editorial QA checklist for this static SOQL vs dynamic SOQL tutorial

  • Confirm that static SOQL examples use square brackets and valid Apex-style bind variables.
  • Confirm that dynamic SOQL examples use Database.query() and do not imply that dynamic SOQL bypasses governor limits.
  • Check that the tutorial clearly recommends static SOQL when only filter values change.
  • Check that dynamic SOQL security guidance mentions bind variables, input validation, and String.escapeSingleQuotes().
  • Verify that official Salesforce documentation links are included for dynamic SOQL, SOQL in Apex, and governor limits.