0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SOQL バインド変数について

Last updated at Posted at 2025-02-20

SalesforceのSOQL(Salesforce Object Query Language)の バインド(Bind Variables) は、Apexコード内で変数を使ってクエリを動的に構築する方法です。
これは、SQLにおける プレースホルダー(?) と同様の役割を果たし、セキュリティやパフォーマンスの向上に役立ちます。


🔹 SOQLのバインド変数とは?

バインド変数を使うと、Apexの変数をSOQLクエリの条件(WHERE句など)に埋め込むことができます。
バインド変数の記述には、変数の前にコロン(:)を付けます。

✅ 例:バインド変数を使ったSOQL

String accountName = 'Acme Corporation';
List<Account> accounts = [SELECT Id, Name FROM Account WHERE Name = :accountName];

上記のコードでは、accountName 変数の値 'Acme Corporation' をSOQLのWHERE句にバインドしています。


🔹 バインド変数を使うメリット

  1. SQLインジェクションを防ぐ

    • 文字列の連結でクエリを構築すると、悪意のあるデータが注入されるリスクがある。
    • バインド変数を使うと、Salesforceが自動的に値をエスケープ処理するため安全。

    ❌ 悪い例(SQLインジェクションのリスクあり)

    String accountName = 'Acme Corporation';
    List<Account> accounts = Database.query('SELECT Id, Name FROM Account WHERE Name = \'' + accountName + '\'');
    

    これは、外部からaccountName' OR Name != '' のような文字列が渡されると、不正なクエリが実行される可能性がある。

  2. クエリパフォーマンスの向上

    • バインド変数を使うと、SalesforceのSOQLエンジンがクエリ計画(Query Plan)をキャッシュしやすくなる。
    • 固定値を直接書くよりも、最適化されたクエリ実行が可能になる。
  3. コードの可読性・再利用性が向上

    • 変数を使うことで、クエリを柔軟にカスタマイズできる。

🔹 バインドできるデータ型

以下のデータ型の変数をバインドできます。

データ型 使用例
String :accountName
Integer :recordCount
Decimal :totalAmount
Boolean :isActive
Date :today
DateTime :currentTime
Id :recordId
Set<T> / List<T> :accountIds(IN句で利用)

🔹 バインド変数の具体例

文字列 (String) のバインド

String targetName = 'Tech Corp';
List<Account> accounts = [SELECT Id, Name FROM Account WHERE Name = :targetName];

👉 targetName の値が Tech Corp なら、その会社のレコードを取得。


数値 (Integer) のバインド

Integer recordCount = 5;
List<Contact> contacts = [SELECT Id, FirstName, LastName FROM Contact LIMIT :recordCount];

👉 LIMIT 句に変数をバインドし、5件だけ取得。


日付 (Date) のバインド

Date today = Date.today();
List<Opportunity> opps = [SELECT Id, Name FROM Opportunity WHERE CloseDate = :today];

👉 今日の CloseDate の商談を取得。


リスト (List<T> または Set<T>) のバインド

複数のIDを検索条件に使う場合、IN 句でバインドできる。

List<Id> accountIds = new List<Id>{'001XXXXXXXXXXXX', '001YYYYYYYYYYYY'};
List<Contact> contacts = [SELECT Id, FirstName FROM Contact WHERE AccountId IN :accountIds];

👉 accountIds に含まれる AccountId を持つ Contact を取得。


オブジェクト (SObject) のバインド

SOQLではSObject全体をバインドできる。
ただし、バインドできるのはそのオブジェクトのIDのみ

Account acc = [SELECT Id FROM Account WHERE Name = 'Tech Corp' LIMIT 1];
List<Contact> contacts = [SELECT Id, FirstName FROM Contact WHERE AccountId = :acc];

👉 accAccount オブジェクトだが、バインドされるのは acc.Id


🔹 バインド変数の制限

  1. WHERE句の右側でのみ使用可能

    • バインド変数は WHERELIMIT 句の右側 でのみ使用可能。
    • SELECTORDER BY では使用できない。

    ❌ NG例

    String fieldName = 'Name';
    List<Account> accounts = [SELECT :fieldName FROM Account]; // エラー!
    
  2. バインド変数のデータ型に注意

    • Set<T>List<T>IN 句で使う場合、型が一致している必要がある。
    • DateDateTime の違いに注意(DateTime には GMT が含まれる)。

🔹 動的SOQL(Database.query)とバインド

Database.query() を使う場合も、バインド変数を使うことが推奨される。

String targetName = 'Tech Corp';
String query = 'SELECT Id, Name FROM Account WHERE Name = :targetName';
List<Account> accounts = Database.query(query);

👉 Database.query() でもバインド変数を利用可能。
👉 直接 + で文字列連結するとSQLインジェクションのリスクがあるため避ける。


🔹 まとめ

項目 説明
バインド変数とは? Apex変数をSOQLクエリに埋め込む機能
メリット SQLインジェクション防止、パフォーマンス向上、可読性向上
バインド可能な型 String, Integer, Date, Id, List<T> など
IN句でリストバインド可能? 可能 (List<T>Set<T> を使用)
動的SOQLでバインド可能? 可能 (Database.query(): を使用)

バインド変数を適切に使うことで、安全でパフォーマンスの高いSOQL を書くことができます!🚀

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?