Skip to main content
Slack の Trailblazer Community がオープンベータを開始しました。ぜひ参加して、リアルタイムで交流しましょう。Slack に参加する

SOQL クエリを作成する

学習の目的

この単元を完了すると、次のことができるようになります。

  • Apex 内に SOQL クエリを記述する。
  • Web コンソールのクエリビルダーを使用して SOQL クエリを実行する。
  • 匿名 Apex を使用して Apex に埋め込まれた SOQL クエリを実行する。
  • 関連レコードを照会する。
メモ

メモ

日本語で受講されている方へ
Challenge は日本語の Trailhead Playground で開始し、かっこ内の翻訳を参照しながら進めていってください。Challenge での評価は英語データを対象に行われるため、英語の値のみをコピーして貼り付けるようにしてください。日本語の組織で Challenge が不合格だった場合は、(1) この手順に従って [Locale (地域)] を [United States (米国)] に切り替え、(2) [Language (言語)] を [English (英語)] に切り替えてから、(3) [Check Challenge (Challenge を確認)] ボタンをクリックしてみることをお勧めします。

翻訳版 Trailhead を活用する方法の詳細は、自分の言語の Trailhead バッジを参照してください。

SOQL 入門

Salesforce からレコードを読み込むには、クエリを作成する必要があります。Salesforce では、保存したレコードの読み込みに使用できる Salesforce Object Query Language (SOQL) を提供しています。SOQL は、標準の SQL 言語と似ていますが、Salesforce Platform 用にカスタマイズされています。

Apex はデータベースに保存されている Salesforce レコードへの直接アクセスが可能であるため、SOQL クエリを Apex コードに埋め込んで、簡単に結果を取得できまます。Apex に埋め込まれた SOQL は、インライン SOQL と呼ばれます。

SOQL クエリを Apex コード内に含めるには、SOQL ステートメントを角括弧でラップして、戻り値を sObject のリストに割り当てます。たとえば、次のコードでは、2 つの項目 (名前と電話) を持つすべての取引先レコードを取得し、Account sObject のリストを返します。

Account[] accts = [SELECT Name,Phone FROM Account];

前提条件

この単元の一部のクエリでは、組織に取引先と取引先責任者があることを前提としています。クエリを実行する前に、いくつかのサンプルデータを作成します。

  1. このコードを Web コンソールで Apex 匿名スクリプトとして実行します。
// Add account and related contact
Account acct = new Account(
    Name='SFDC Computing',
    Phone='(415)555-1212',
    NumberOfEmployees=50,
    BillingCity='San Francisco');
insert as user acct;
// Once the account is inserted, the sObject will be
// populated with an ID.
// Get this ID.
ID acctID = acct.ID;
// Add a contact to this account.
Contact con = new Contact(
    FirstName='Carol',
    LastName='Ruiz',
    Phone='(415)555-1212',
    Department='Wingo',
    AccountId=acctID);
insert as user con;
// Add account with no contact
Account acct2 = new Account(
    Name='The SFDC Query Man',
    Phone='(310)555-1213',
    NumberOfEmployees=50,
    BillingCity='Los Angeles',
    Description='Expert in wing technologies.');
insert as user acct2;
Note

取引先責任者 sObject の名前項目は複合項目であり、 取引先責任者の FirstName、LastName、MiddleName、Suffix 項目の連結です。[設定] のオブジェクトマネージャーにリストされるのは名前の複合項目のみです。ただし、この単元のサンプル Apex コードは、複合項目を構成する個別の項目を参照しています。

クエリビルダーを使用する

Web コンソールにはクエリビルダーが含まれており、SOQL クエリを実行して結果を表示できます。クエリビルダーを使用して、すばやくデータベースを調査できます。そのため、SOQL クエリを Apex コードに追加する前のテストに適しています。

次の SOQL の例を実行してみましょう。

  1. Web コンソールで、Ctrl+Shift+P (Windows) または Cmd+Shift+P (macOS) を押してコマンドパレットを開きます。
  2. SFDX: Create Query in SOQL Builder (SFDX: SOQL ビルダーでクエリを作成) と入力し、Enter キーを押します。
  3. SOQL ファイル名に TestQueries と入力し、Enter キーを押します。
  4. 出力ディレクトリに [scripts/soql] を選択し、Enter キーを押します。
  5. [From (参照元)] 項目で [Account (取引先)] を選択します。
  6. [Fields (項目)] 項目で、[Name (名前)] と [Phone (電話)] を選択します。
  7. SOQL クエリボックスの下で、完全な SOQL クエリが次のとおりであることを確認します: SELECT Name,Phone FROM Account
  8. [Run Query (クエリを実行)] をクリックします。

組織内のすべての取引先レコードが、新しい [SOQL Query Results (SOQL クエリ結果)] タブに項目のある行として表示されます。クエリ結果を .csv または .json ファイルとしてエクスポートできます。

TestQueries.soql スクリプトファイルと [SOQL Queries Result (SOQL クエリ結果)] パネルが Web コンソールで開いている状態。

未加工の SOQL クエリを実行する

クエリビルダーは有効な SOQL クエリの作成に役立ちますが、必ずしも使用する必要はありません。構文に自信がある場合は使用しなくてもかまいません。Web コンソールでも未加工の SOQL クエリを実行できます。

次の SOQL の例を実行してみましょう。

  1. Web コンソールで、Ctrl+Shift+P (Windows) または Cmd+Shift+P (macOS) を押してコマンドパレットを開きます。
  2. SFDX: Create SOQL Query (SFDX: SOQL クエリを作成) と入力し、Enter キーを押します。
  3. SOQL ファイル名に TestQueries1 と入力し、Enter キーを押します。
  4. 出力ディレクトリに [scripts/soql] を選択し、Enter キーを押します。
  5. 次の SOQL クエリを入力します: SELECT Name,Phone FROM Account
  6. ファイルの上部にある [Run Query (クエリを実行)] をクリックします。
  7. [REST API] を選択し、Enter キーを押します。REST API を使用して SOQL クエリを実行する方法は、取引先の作成や取引先責任者の検索など、組織のデータに対して操作を行う場合に最適です。

クエリ結果は [Output (出力)] パネルに表示され、.sfdx/data ディレクトリに CSV ファイルが作成されます。

TestQueries1.soql スクリプトファイルと [Output (出力)] パネルが Web コンソールで開いている状態。[Output (出力)] パネルとクエリ結果の .csv ログファイルが強調表示されています。

基本的な SOQL 構文

基本的な SOQL クエリの構文を次に示します。

SELECT fields FROM ObjectName [WHERE Condition]

WHERE 句は省略可能です。まず簡単なクエリから始めましょう。たとえば、次のクエリは取引先を取得し、各取引先の名前項目と電話項目を取得します。

SELECT Name,Phone FROM Account

このクエリは 2 つの部分で構成されます。

  1. SELECT Name,Phone: この部分には、取得する項目がリストされます。項目は、SELECT キーワードの後にカンマ区切りリストで指定します。または、項目を 1 つだけ指定できます。この場合、カンマは不要です (SELECT Phone など)。
  2. FROM Account: この部分では、取得する標準またはカスタムオブジェクトを指定します。この例では、Account です。Invoice_Statement という名前のカスタムオブジェクトの場合は、Invoice_Statement__c になります。

高度な操作

他の SQL 言語と異なり、* を指定してオブジェクトのすべての項目を取得することはできません。その代わりに、FIELDS() キーワードを使用して、すべての標準項目 (FIELDS(STANDARD))、すべてのカスタム項目 (FIELDS(CUSTOM))、またはすべての項目 (FIELDS(ALL)) をオブジェクトから取得できます。詳細は、「SOQL および SOSL リファレンス」の「SELECT」を参照してください。

SELECT 句に (明示的にまたは FIELDS() キーワードを使用して) 指定していない項目にアクセスしようとすると、項目が取得されていないため、エラーになります。

Id (ID) 項目をクエリに指定する必要はありません。Apex クエリでは、指定されたかどうかに関係なく常に ID 項目が返されます。たとえば、SELECT Id,Phone FROM Account と SELECT Phone FROM Account は同等のステートメントです。ただし、項目は少なくとも 1 つリストしなければならないため、Id (ID) 項目のみを取得する場合だけは指定する必要があります (SELECT Id FROM Account など)。Id (ID) 項目は、指定しないと表示されないため、クエリエディターでクエリを実行するときにも Id (ID) 項目の指定が必要になる場合があります。

条件を指定してクエリ結果を絞り込む

組織に複数の取引先がある場合、すべてが返されます。返される取引先を、特定の条件を満たす取引先に制限する場合、この条件を WHERE 句内に追加できます。次の例では、名前が SFDC Computing の取引先のみが取得されます。文字列の比較では、大文字と小文字は区別されません。

SELECT Name,Phone FROM Account WHERE Name='SFDC Computing'

WHERE 句には、論理演算子 (AND、OR) と括弧を使用してグループ化した複数の条件を含めることができます。たとえば、次のクエリは SFDC Computing という名前で、従業員数が 25 より多い取引先をすべて返します。

SELECT Name,Phone FROM Account WHERE (Name='SFDC Computing' AND NumberOfEmployees>25)

次の別の例では、より複雑な条件が指定されています。このクエリは、以下のレコードをすべて返します。

  • 「SFDC Computing」という名前のすべての取引先、または
  • 従業員数が 25 人を超え、請求先市区町村がロサンゼルスであるすべての取引先
SELECT Name,Phone FROM Account
   WHERE (Name='SFDC Computing' OR (NumberOfEmployees>25 AND BillingCity='Los Angeles'))

高度な操作

比較に等号演算子 (=) を使用する代わりに、LIKE 演算子を使用してあいまい一致検索を実行することができます。たとえば、条件 WHERE Name LIKE 'SFDC%' を使用して、名前が SFDC で開始する取引先をすべて取得できます。% ワイルドカード文字は、0 個以上の文字に一致します。_ 文字を使用して 1 文字のみに一致させることもできます。

クエリ結果に順序を付ける

クエリが実行されると、Salesforce から返されるレコードは特定の順序にはなっていないため、リスト内のレコードの順序はクエリを実行するたびに変わる可能性があります。ただし、ORDER BY 句を追加し、レコードの並び替え基準にする項目を指定することで、返されるレコードセットを並び替えることができます。次の例では、取得されたすべての取引先を名前項目に基づいて並び替えます。

SELECT Name,Phone FROM Account ORDER BY Name

デフォルトの並び替え順は、アルファベットの昇順 (ASC を指定) です。前のステートメントは、次のステートメントと同等です。

SELECT Name,Phone FROM Account ORDER BY Name ASC

順序を逆にするには、DESC キーワードを使用して降順にします。

SELECT Name,Phone FROM Account ORDER BY Name DESC

数値項目とテキスト項目を含む、ほとんどの項目に基づいて並び替えできます。リッチテキストや複数選択リストなどの項目に基づく並び替えはできません。

これらの SOQL ステートメントをクエリエディターで試し、返されるレコードの順序が名前項目に基づいてどのように変化するのかを確認してみましょう。

返されるレコード数を制限する

LIMIT n 句を追加すると (n は返されるレコード数)、返されるレコード数を任意の数に制限できます。どのレコードが返されるかは考慮せずにレコードのサブセットを処理することだけが目的の場合は、結果セットを制限すると便利です。たとえば、次のクエリでは返される最初の取引先を取得します。LIMIT 1 を使用する場合、返される値は 1 件の取引先であり、リストではないので注意してください。

Account oneAccountOnly = [SELECT Name,Phone FROM Account LIMIT 1];

句を組み合わせる

1 つのクエリ内に、省略可能な句を次の順序で組み合わせることができます。

SELECT Name,Phone FROM Account
                   WHERE (Name = 'SFDC Computing' AND NumberOfEmployees>25)
                   ORDER BY Name
                   LIMIT 10

Web コンソールで Apex 匿名スクリプトを使用して、Apex で次の SOQL クエリを実行します。実行後、デバッグログでデバッグステートメントを調査します。1 件のサンプル取引先が返されます。

Account[] accts = [SELECT Name,Phone FROM Account
                   WHERE (Name='SFDC Computing' AND NumberOfEmployees>25)
                   ORDER BY Name
                   LIMIT 10];
System.debug(accts.size() + ' account(s) returned.');
// Write all account info
System.debug(accts);

SOQL クエリの変数にアクセスする

Apex の SOQL ステートメントは、前にコロン (:) が付けられた Apex コードの変数と式を参照できます。SOQL ステートメント内でローカル変数を使用することを、バインドと呼びます。

次の例は、WHERE 句内で targetDepartment 変数を使用する方法を示します。

String targetDepartment = 'Wingo';
Contact[] techContacts = [SELECT FirstName,LastName
                          FROM Contact WHERE Department=:targetDepartment];

関連レコードを照会する

Salesforce 内のレコードは、リレーション (参照関係または主従関係) を介して互いにリンクできます。たとえば、取引先責任者には取引先への参照関係があります。取引先責任者を作成または更新するとき、その取引先責任者を取引先に関連付けることができます。同じ取引先に関連付けられている取引先責任者は、取引先のページの関連リストに表示されます。同様に、Salesforce ユーザーインターフェースで関連レコードを表示したり、SOQL で関連レコードを照会したりできます。

親レコードに関連する子レコードを取得するには、子レコードへの内部クエリを追加します。内部クエリの FROM 句は、Salesforce オブジェクト名ではなくリレーション名に対して実行されます。次の例には、返される取引先ごとに関連付けられているすべての取引先責任者を取得する内部クエリが含まれます。FROM 句では、Contacts リレーションを指定しています。これは、取引先と取引先責任者をリンクする Account のデフォルトのリレーションです。

SELECT Name, (SELECT LastName FROM Contacts) FROM Account WHERE Name = 'SFDC Computing'

次の例は、サンプル SOQL クエリを Apex に埋め込み、sObject に対して Contacts リレーション名を使用して、SOQL の結果から子レコードを取得する方法を示します。

Account[] acctsWithContacts = [SELECT Name, (SELECT FirstName,LastName FROM Contacts)
                               FROM Account
                               WHERE Name = 'SFDC Computing'];
// Get child records
Contact[] cts = acctsWithContacts[0].Contacts;
System.debug('Name of first associated contact: '
             + cts[0].FirstName + ', ' + cts[0].LastName);

ドット表記を使用して子オブジェクト (取引先責任者) から親の項目 (Account.Name) にトラバースできます。たとえば、次の Apex スニペットでは、名が Carol の取引先責任者レコードを照会し、取引先と取引先責任者間のリレーションをトラバースすることで、Carol が関連付けられている取引先の名前を取得できます。

Contact[] cts = [SELECT Account.Name FROM Contact
                 WHERE FirstName = 'Carol' AND LastName='Ruiz'];
Contact carol = cts[0];
String acctName = carol.Account.Name;
System.debug('Carol\'s account name is ' + acctName);
Note

このセクションの例は、標準オブジェクトに基づいてます。カスタムオブジェクトも、カスタムリレーションを使用して一緒にリンクできます。カスタムリレーション名は __r サフィックスで終わります。たとえば、請求書明細は、Invoice_Statement__c カスタムオブジェクトの Line_Items__r リレーションを介して品目名にリンクします。

SOQL for ループを使用してレコードを一括で照会する

SOQL クエリの結果をリストに保存し、そのリストをループしてすべてのレコードを処理する方法は、一見すると自然に思えるかもしれません。ですが、特に SOQL クエリが数千件のレコードを返す場合、この方法では処理負荷が高くなります。Salesforce のようなマルチテナント環境で作業する場合は、実行制限内に収めることが重要です。ヒープ制限の超過を避けるには、代わりに variable_list を使用する SOQL for ループで処理します。SOQL for ループは、レコードを取得する際に効率的なチャンク処理メソッドを使用し、次の構文で記述します:

for (variable_list : [soql_query]) {
    for (variable : variable_list) {
       // Update records
    }
    update variable_list;
}

variable_list は、soql_query で返される sObject と同じデータ型である必要があります。

この形式を使用すると、外側のループは、レコードごとに 1 回ではなく、200 個の sObject の一括処理ごとに 1 回実行されます。この形式では、レコードを一括更新し、一括 DML オペレーションを実行できるため、ヒープ制限に達する可能性を減らせます。

以下は、匿名 Apex で実行できる例です。

// Create a savepoint to prevent test data from being committed to the database
Savepoint sp = Database.setSavepoint();
insert as user new List<Account>{new Account(Name = 'for loop 1'),
                     new Account(Name = 'for loop 2'),
                     new Account(Name = 'for loop 3')};
// The sObject list format executes the for loop once per returned batch
// of records
Integer i=0;
Integer j=0;
for (Account[] accts : [SELECT Id FROM Account WHERE Name LIKE 'for loop _']) {
    j = accts.size();
    i++;
    for (Account a : accts) {
       // Your code here
    }
    update as user accts;
}
Assert.areEqual(3, j); // The list should contain the three accounts
                       // named 'yyy'
Assert.areEqual(1, i); // Since a single batch can hold up to 200 records and,
                       // only three records should have been returned, the
                       // loop should have executed only once
// Revert the database to the original state
Database.rollback(sp);

リソース

Salesforce ヘルプで Trailhead のフィードバックを共有してください。

Trailhead についての感想をお聞かせください。[Salesforce ヘルプ] サイトから新しいフィードバックフォームにいつでもアクセスできるようになりました。

詳細はこちら フィードバックの共有に進む