はじめに
動的 SOQL であるDatabase.query(String)
は公式のドキュメントに普通のやり方のように書かれているためか、未だにそこそこな頻度で見かけることがあるので啓発の意味を込めて書きます。SELECT するフィールドを動的に生成する必要があるなどの特別な事情がない限り使わないでください。
結論
インライン SOQL を使ってください
List<Account> accounts = Database.query('SELECT Id FROM Account'); // Bad
List<Account> accounts = [SELECT Id FROM Account]; // Good
理由
1. セキュリティリスクを考慮する必要がある
公式でも言及されてますが文字列でクエリを渡しているため、画面などからのインプットを素通しすると SOQL インジェクションのリスクがあります。escapeSingleQuotes
を使えば問題ないですが、いちいちメソッドを呼ぶ必要があるので忘れがちです。インライン SOQL であれば
[SELECT Id FROM Account WHERE Id = :inputId]
のようにバインドで変数を呼ぶだけでいいので考慮することがより少ないです。
2. エディタの補助機能を活かせない
VSCode などのエディタを使うと文字列としか認識されていないため、オブジェクトの項目名がサジェストされない上に、項目名が間違っていたとしても警告が出ないため実行しないとエラーに気付けません。これらは効率と品質面に悪い影響しか与えません。
3. 項目の使用場所に引っ掛からない
オブジェクトの項目のページから、その項目がどの Apex クラスで使われているかを確認できますが、文字列としか認識されていないためこの機能に引っかかりません。これによって項目の影響調査がしづらくなり保守性が下がってしまいます。また、通常どこかで項目が使用されていれば項目削除はできませんが、動的 SOQL でやっていたがために項目削除ができて障害が起きる...というようなリスクも出てきます。
ということで動的 SOQL はインライン SOQL に比べるとほとんどデメリットしかないので使うのはできる限り控えましょうという話でした。