SOQL For ループ
SOQL for ループは SOQL クエリで返されたすべての sObject レコードを反復します。
SOQL for ループの構文は次のいずれかになります。
または
1for (variable : [soql_query]) {
2 code_block
3}1for (variable_list : [soql_query]) {
2 code_block
3}
variable および variable_list は、soql_query で返される sObject と同じデータ型である必要があります。標準 SOQL クエリと同様、[soql_query] ステートメントは、: 構文を使用して WHERE 句のコード式を参照することができます。次に例を示します。
1String s = 'Acme';
2for (Account a : [SELECT Id, Name from Account
3 where Name LIKE :(s+'%')]) {
4 // Your code
5}次の例では、SOQL クエリからのリストの作成と DML update メソッドを結合します。
1// Create a list of account records from a SOQL query
2List<Account> accs = [SELECT Id, Name FROM Account WHERE Name = 'Siebel'];
3
4// Loop through the list and update the Name field
5for(Account a : accs){
6 a.Name = 'Oracle';
7}
8
9// Update the database
10update accs;SOQL For ループと標準 SOQL クエリの比較
SOQL for ループは、sObjects を取得するために使用するメソッドが、標準 SOQL ステートメントとは異なります。「SOQL および SOSL クエリ」で説明する標準クエリはクエリの count または多数のオブジェクトレコードを取得できますが、SOQL for ループは、SOAP API の query メソッドと queryMore メソッドのコールで効率的なチャンクを使用して、すべての sObject を取得します。開発者は常に SOQL for ループを使用して、多数のレコードを返すクエリ結果を処理し、ヒープサイズの制限に達するのを回避します。
集計関数を含むクエリでは、queryMore をサポートしません。for ループで 2,000 を超える行を返す集計関数を含むクエリを使用すると、実行時例外が発生します。
SOQL For ループの形式
SOQL for ループは、単一の sObject 変数を使用して一度に 1 件のレコードを処理するか、sObject リストを使用して一度に 200 個の sObject を一括処理できます。
- 単一の sObject 形式は for ループの <code_block> を sObject レコードごとに 1 回実行します。そのため、理解しやすく、簡単に使用できますが、for ループの本文内でデータ操作言語 (DML) ステートメントを使用すると、効率性が大幅に低下します。DML ステートメントは、一度に 1 つの sObject の処理のみを完了します。
- sObject リスト形式は for ループの <code_block> を 200 件の sObject のリストごとに 1 回実行します。そのため、多少理解しにくく、使用が難しくなりますが、for ループの本文内で DML ステートメントを使用する必要がある場合に最適です。DML ステートメントは、sObject のリストを一括処理します。
たとえば、次のコードは 2 種類の SOQL クエリ for ループの差異を示します。
1// Create a savepoint because the data should not be committed to the database
2Savepoint sp = Database.setSavepoint();
3
4insert new Account[]{new Account(Name = 'yyy'),
5 new Account(Name = 'yyy'),
6 new Account(Name = 'yyy')};
7
8// The single sObject format executes the for loop once per returned record
9Integer i = 0;
10for (Account tmp : [SELECT Id FROM Account WHERE Name = 'yyy']) {
11 i++;
12}
13System.assert(i == 3); // Since there were three accounts named 'yyy' in the
14 // database, the loop executed three times
15
16// The sObject list format executes the for loop once per returned batch
17// of records
18i = 0;
19Integer j;
20for (Account[] tmp : [SELECT Id FROM Account WHERE Name = 'yyy']) {
21 j = tmp.size();
22 i++;
23}
24System.assert(j == 3); // The list should have contained the three accounts
25 // named 'yyy'
26System.assert(i == 1); // Since a single batch can hold up to 200 records and,
27 // only three records should have been returned, the
28 // loop should have executed only once
29
30// Revert the database to the original state
31Database.rollback(sp);