SOQLでバインド変数を使うときに押さえておきたいポイントについてです。動的クエリの処理を実装する際に、クエリ文字列の生成とクエリの実行を別クラスで行うような処理を書いてみました。
すごくざっくりですがこんな感じの書き方です。
呼び出し元のコントローラクラス (BindSearchController.cls)
動的クエリ取得用のクラス (BindSearchAction.cls)
コントローラクラスで用意した検索条件をBindSearchAction.clsに渡し、SOQLクエリを用意したらコントローラクラスに戻す。取得したクエリはBindSearchController.cls側で実行する。というような流れです。条件に一致するレコードがあれば値を取得できます。
このような方法で実装するときに注意しなくてはならないのが、バインド変数に指定した変数名は呼び出し元の変数名と同じ名前にする必要があるという点です。
例えば上に記載した処理の場合は、どちらのクラスも検索条件の値は、変数「key」にセットされています。このときに、コントローラクラス側の変数名が「key」ではなく「searchKey」のように別の名前が使われていたとします。
そうなるとバインド変数としてクエリにセットされた「key」という変数は、コントローラクラス側には存在しなくなってしまうため、クエリ実行時にExceptionが発生してしまいます。
このようにクエリのバインド変数は変数の値がセットされるのではなく、クエリ実行時までは、変数名の文字列がセットされているように扱われます。
この問題を回避するには、クエリの生成からクエリの実行までは同じクラス内で完結するように実装するのが一番だと思います。
このような問題が発生したりするので、クエリの生成と実行を別クラスに分けて、かつバインド変数を使うような処理の場合は注意が必要です。