【図解】Salesforce フローのループ内で更新してはいけない理由とコレクション変数の使い方
このページには広告リンクを含みます。
ループの中のレコード更新で止まる仕組み
Salesforce は基盤を複数の組織で共有しているため、1トランザクションで使える量に上限(ガバナ制限)を設けています。ループが関わる主な数字はこの4つです。
| 上限 | 値 | 消費する要素 | ループの中に置くと |
|---|---|---|---|
| SOQL の回数 | 100回 | レコードを取得、絞り込み条件つきの更新・削除 | 件数分増える |
| 取得行 | 50,000行 | レコードを取得 | 重複して取ると早く尽きる |
| DML の回数 | 150回 | レコードを作成・更新・削除 | 件数分増える |
| DML の対象行 | 10,000行 | レコードを作成・更新・削除 | 外に出しても変わらない |
要素1つにつき1回というのが数え方の基本です。要素が1つでも、ループの中にあれば周回の数だけ実行されます。
例として、取引先の更新で動くフローを考えます。取引先責任者を取得し、ループで1件ずつレコードを更新します。取引先責任者が30件の取引先なら DML は30回で通ります。200件の取引先では、151件目の更新で止まります。テストデータが数件だと気付かないのは、このためです。
実際にはもっと手前で止まることもあります。同じトランザクションで動く他のフローや Apex トリガーも、同じ枠を使うからです。
失敗すると、障害パスを付けていてもトランザクション全体がロールバックされます。つまり取引先の更新そのものが取り消され、ユーザーの画面にはエラーが出ます。
コレクション変数と割り当てで直す手順
直し方は決まっています。Trailhead の説明は「取得はループの前、書き込みはループの後」です。

- レコードを取得:ループの前で、必要なレコードをまとめて取ります。
- リソースを作る:レコード型で「複数の値を許可」にした変数(レコードのコレクション変数)を用意します。名前は
UpdatedContactsのように中身が分かるものにします。 - ループ:取得したコレクションを渡します。
- 割り当て(1):現在の項目(Current Item)の項目に、新しい値を入れます。
- 割り当て(2):演算子「追加」(Add)で、現在の項目をコレクション変数に足します。1つの割り当て要素に2行まとめても構いません。
- レコードを更新:ループの「最後の項目の後」(After Last)の線に置き、コレクション変数を渡します。
コレクションへの追加は変数の操作なので、DML を消費しません。書き込みはループの後の1回だけです。
手順5を忘れると、更新要素に空のコレクションが渡ります。現在の項目の中身は次の周回で入れ替わるため、そこに入れた値は追加しない限り残りません。
SOQL 101 エラーも同じ原因
Too many SOQL queries: 101 は、1トランザクションで SOQL を100回より多く使ったときのエラーです。フローでは次の置き方が原因になります。
- ループの中のレコードを取得
- ループの中の、絞り込み条件で対象を指定するレコードを更新・削除(この形は SOQL と DML の両方を1回ずつ使う)
- 取得が多いサブフローをループの中で呼ぶ
Salesforce の数え方では、絞り込み条件つきの更新要素も問い合わせを1回使います。ループの中で親を探して更新する形は、両方の枠を同時に減らすことになります。
Flow が自動でまとめる範囲と、まとめない範囲
「フローは自動でバルク化される」と聞いて、ループも大丈夫だと考えるのは間違いです。自動でまとまるのは、別々のインタビューが同じ要素に着いたときだけです。

| 場面 | 例 | DML の回数 |
|---|---|---|
| 複数のインタビューが同じ要素に着く | データローダで100件の商談を更新し、100のインタビューが同じレコードを更新に到達 | まとめて1回 |
| 1つのインタビューの中のループ | 1件の取引先の変更で動き、ループで100件を1件ずつ更新 | 100回 |
| 1つのインタビューでループの外から更新 | 同じ処理をコレクションで1回更新 | 1回 |
大量取り込みは別の話として考えておきます。判断ガイドの例では、20,000件を200件ずつ取り込むと、トリガーは100回起動します。1件ずつの保存で問題がなくても、200件単位で動いたときの消費は別に確かめておく必要があります。
外に出しても残る上限
コレクションで DML を1回にしても、対象行の上限は残ります。さらに更新したレコードの自動化も同じトランザクションで動きます。
- 対象を絞る:Trailhead の例では、全取引先責任者のチェックを外すスケジュールフローが10,000件を超えて失敗します。レコードを更新の条件で、チェックが付いているレコードだけを対象にすれば件数を抑えられます。同じ絞り込みは、開始要素とレコードを取得にも設定できます。
- トランザクションを分ける:待機要素を挟むと新しいトランザクションが始まります。
- 印を付けて後で処理する:判断ガイドは、即時でなくてよい大量の処理について、トリガーでレコードに印を付け、スケジュールジョブでまとめて処理する方法を示しています。
- Apex に任せる:突き合わせが複雑、件数が数千を超える、途中で取り消す制御が要る場合です。呼び出し可能な Apex でフローから呼ぶ方法もあります。
項目の写し替えが目的なら、変換要素(Transform)でループ自体を減らせる場合もあります。
公開前に確かめること
本番で止めないためのチェックです。編集部のおすすめとして挙げます。
- テストデータに、1件の親に子が200件以上あるパターンを入れる
- データローダなどで200件を一度に更新してみる
- ループの線の中に、レコードの取得・作成・更新・削除とサブフローがないか目で見る
- 同じオブジェクトで動く他のフローや Apex トリガーの消費も足して考える
Salesforce Code Analyzer のフロー用ルールも使えます。パイプラインに組み込むと、人の目での見落としを減らせます。
関連記事
- Salesforce フローの種類と選び方:高速項目更新とアクションと関連レコードの違い
- 保存時の実行順序を図解:同じトランザクションで何が動くか
- 外部システムとの連携パターン:大量データを Bulk API 2.0 に任せる判断
- Platform App Builder の勉強法:フローの設計を試験範囲とつなげて学ぶ
よくある質問
- Salesforce フローのループの中でレコードを更新してはいけないのはなぜですか?
- ループの中のレコードを更新要素は1件ごとに1回の DML を使うためです。上限は1トランザクション150回なので、151回目で失敗し、トランザクション全体が取り消されます。
- ループ内の更新はどう直せばよいですか?
- ループの中では割り当て要素で値を変え、レコードのコレクション変数に追加します。ループを抜けた後にレコードを更新要素を1つ置き、コレクションをまとめて渡せば、DML は1回で済みます。
- フローで Too many SOQL queries: 101 が出る原因は何ですか?
- 1トランザクションで SOQL を100回より多く使ったときに出るエラーです。ループの中のレコードを取得要素や、絞り込み条件つきの更新・削除要素が主な原因で、同じトランザクションの他の自動化の分も合算されます。
- レコードが1万件を超える場合はフローで更新できますか?
- DML の対象は1トランザクション10,000行までなので、コレクションでまとめても1回で10,000行を超える更新はできません。絞り込みで対象を減らす、処理を分ける、Apex のバッチを使うなどを検討します。