Using Apex Variables in SOQL and SOSL Queries

SOQL and SOSL statements in Apex can reference Apex code variables and expressions if they’re preceded by a colon (:). This use of a local code variable within a SOQL or SOSL statement is called a bind. The Apex parser first evaluates the local variable in code context before executing the SOQL or SOSL statement. Bind expressions can be used as:

  • The search string in FIND clauses.
  • The filter literals in WHERE clauses.
  • The value of the IN or NOT IN operator in WHERE clauses, allowing filtering on a dynamic set of values. Note that this is of particular use with a list of IDs or Strings, though it works with lists of any type.
  • The division names in WITH DIVISION clauses.
  • The numeric value in LIMIT clauses.
  • The numeric value in OFFSET clauses.

For example:

1Account A = new Account(Name='xxx');
2insert as user A;
3Account B;
4
5// A simple bind
6B = [SELECT Id FROM Account WHERE Id = :A.Id WITH USER_MODE];
7
8// A bind with arithmetic
9B = [SELECT Id FROM Account 
10     WHERE Name = :('x' + 'xx') WITH USER_MODE];
11
12String s = 'XXX';
13
14// A bind with expressions
15B = [SELECT Id FROM Account 
16     WHERE Name = :'XXXX'.substring(0,3) WITH USER_MODE];
17
18// A bind with INCLUDES clause
19B = [SELECT Id FROM Account WHERE :A.TYPE INCLUDES (‘Customer – Direct; Customer – Channel’) WITH USER_MODE];
20
21// A bind with an expression that is itself a query result
22B = [SELECT Id FROM Account
23     WHERE Name = :[SELECT Name FROM Account
24                    WHERE Id = :A.Id WITH USER_MODE].Name 
25                    WITH USER_MODE];
26
27Contact C = new Contact(LastName='xxx', AccountId=A.Id);
28insert as user new Contact[]{C, new Contact(LastName='yyy', 
29                                    accountId=A.id)};
30
31// Binds in both the parent and aggregate queries
32B = [SELECT Id, (SELECT Id FROM Contacts
33                 WHERE Id = :C.Id)
34     FROM Account
35     WHERE Id = :A.Id WITH USER_MODE];
36
37// One contact returned
38Contact D = B.Contacts;
39
40// A limit bind
41Integer i = 1;
42B = [SELECT Id FROM Account WITH USER_MODE LIMIT :i];
43
44// An OFFSET bind
45Integer offsetVal = 10;
46List<Account> offsetList = [SELECT Id FROM Account WITH USER_MODE OFFSET :offsetVal];
47
48// An IN-bind with an Id list. Note that a list of sObjects
49// can also be used--the Ids of the objects are used for 
50// the bind
51Contact[] cc = [SELECT Id FROM Contact WITH USER_MODE LIMIT 2];
52Task[] tt = [SELECT Id FROM Task WHERE WhoId IN :cc WITH USER_MODE];
53
54// An IN-bind with a String list
55String[] ss = new String[]{'a', 'b'};
56Account[] aa = [SELECT Id FROM Account 
57                WHERE AccountNumber IN :ss WITH USER_MODE];
58
59// A SOSL query with binds in all possible clauses
60
61String myString1 = 'aaa';
62String myString2 = 'bbb';
63Integer myInt3 = 11;
64String myString4 = 'ccc';
65Integer myInt5 = 22;
66
67List<List<SObject>> searchList = [FIND :myString1 IN ALL FIELDS 
68                                  RETURNING 
69                                     Account (Id, Name WHERE Name LIKE :myString2
70                                              LIMIT :myInt3), 
71                                     Contact, 
72                                     Opportunity, 
73                                     Lead 
74                                  WITH DIVISION =:myString4 
75                                  LIMIT :myInt5];
Apex bind variables aren’t supported for the units parameter in the DISTANCE function. This query doesn’t work.
1String units = 'mi';
2List<Account> accountList = 
3    [SELECT ID, Name, BillingLatitude, BillingLongitude 
4     FROM Account 
5     WHERE DISTANCE(My_Location_Field__c, GEOLOCATION(10,10), :units) < 10];

Note