tyoshikawa1106のブログ

- Force.com Developer Blog -

SFDC:SOQLとString.escapeSingleQuotes()

通常、Name項目を条件にAccountオブジェクトを検索したい場合は、こんな感じのクエリでレコードを取得できます。

f:id:tyoshikawa1106:20140825203510p:plain


このクエリでKeyに指定した「株式会社 セールスフォース・ドットコム」のレコードを取得できます。

f:id:tyoshikawa1106:20140825203604p:plain


ですが、このクエリでは検索条件にクエリ文字列を追加されたりすると、不正なクエリが実行されてしまいます。例えばこんな感じのクエリです。

f:id:tyoshikawa1106:20140825203754p:plain


このように検索条件の後に「OR」条件を追加されたりするとクエリ文字列が変更されてしまい、思わぬレコードにアクセスされてしまいます。

f:id:tyoshikawa1106:20140825204223p:plain


もちろん、Salesforceにはプロファイルやロールなどによって、ユーザが参照権限の無いレコードにはアクセスできないようなしくみが用意されていますが、それでもこのようなクエリは実行できないようにする必要があります。


Apexにはこのようなクエリを実行できないようにするための「escapeSingleQuotes」関数が用意されています。


この関数を先程の不正なクエリに追加すると・・

f:id:tyoshikawa1106:20140825203735p:plain


このようにエスケープ文字列の「'\''」がただの文字列として変換され、不正なクエリが実行できないようになります。

f:id:tyoshikawa1106:20140825215228p:plain


画面の入力値を検索条件に指定するようなSOQLクエリを実行する機能の場合は、必ず「escapeSingleQuotes」を追加するようにしましょう。


また、SOQLのクエリ実行には次の方法もあります。

f:id:tyoshikawa1106:20140825205959p:plain


この方法でクエリを実行した場合は自動で「escapeSingleQuotes」と同じように変換してくれるので自分で指定する必要はありません。

f:id:tyoshikawa1106:20140825210059p:plain:w300


という感じで、ここまでがSOQLとString.escapeSingleQuotes()についての基本的な使い方についてです。ここからもう少し検証してみたいと思います。


検索画面を開発する際に前方一致のあいまい検索を実装するようなケースが多々あると思います。その場合はLIKE条件を使って対応できます。次のような感じです。

f:id:tyoshikawa1106:20140825212522p:plain


このクエリで「株式会社 セールスフォース」を含むレコードを取得できます。「%」を「escapeSingleQuotes」の中に書くか、外に書くかは人によって違うかもしれませんが、「%」はエスケープ文字列ではないので中に書いても変換されたりはしません。


もしここで「株式会社 セールスフォース・ドットコム」と似た名前の「株式会社 セールスフォース%ドットコム」を検索したい場合、次のようなクエリを実行すると思います。

f:id:tyoshikawa1106:20140825213103p:plain


これを実行すると次の結果となります。

f:id:tyoshikawa1106:20140825213234p:plain


このように「%」はLIKE条件として使われるため、「株式会社 セールスフォース%ドットコム」のみを取得することはできません。「%」はエスケープ文字列ではないので「escapeSingleQuotes」があっても同じ結果となります。


このような検索対象に「%」が含まれるケースはあまり無いと思うのですが、LIKE検索を行う場合はこのような挙動になることを意識しておいた方が良さそうです。(もしLIKEで「%」を検索条件に使いたい場合は、escapeSingleQuotesを使わずに自分で対応しないとダメっぽいです。。)


最後に、LIKE検索ではなく完全一致検索の場合は対象に「%」が含まれていても問題なく検索できます。

f:id:tyoshikawa1106:20140825214300p:plain

f:id:tyoshikawa1106:20140825214330p:plain

追記

LIKE検索の問題に関する続きの記事を書きました。