Schreiben von SOQL-Abfragen
Lernziele
Nachdem Sie diese Lektion abgeschlossen haben, sind Sie in der Lage, die folgenden Aufgaben auszuführen:
- Schreiben von SOQL in Apex
- Ausführen von SOQL-Abfragen mithilfe des Abfrage-Editors in der Entwicklerkonsole
- Ausführen von in Apex eingebetteten SOQL-Abfragen mithilfe von anonymem Apex-Code
- Abfragen verknüpfter Datensätze
Erste Schritte mit SOQL
Zum Auslesen eines Datensatzes aus Salesforce müssen Sie eine Abfrage schreiben. Salesforce bietet die Salesforce Object Query Language, kurz SOQL, mit der gespeicherte Datensätze ausgelesen werden können. SOQL ähnelt der Standardsprache SQL, ist jedoch auf die Salesforce Platform zugeschnitten.
Da Apex direkten Zugriff auf in der Datenbank gespeicherte Salesforce-Datensätze hat, können Sie SOQL-Abfragen in Ihren Apex-Code einbetten und erhalten so auf direkte Weise Ergebnisse. Wenn SOQL in Apex eingebettet ist, wird es als Inline-SOQL bezeichnet.
Um SOQL-Abfragen in den Apex-Code einzufügen, setzen Sie die SOQL-Anweisung in eckige Klammern und weisen Sie den Rückgabewert einer Liste von sObjects zu. Mit folgendem Beispiel etwa werden alle Accountdatensätze mit zwei Feldern, "Name" und "Phone", abgerufen und es wird eine Liste von Account-sObjects zurückgegeben.
Account[] accts = [SELECT Name,Phone FROM Account];
Voraussetzungen
Einige Abfragen in diesem Abschnitt setzen voraus, dass die Organisation über Accounts und Kontakte verfügt. Bevor Sie die Abfragen ausführen, erstellen Sie einige Beispieldaten.
- Öffnen Sie in der Entwicklerkonsole über das Menü Debug das Fenster für die anonyme Ausführung.
- Fügen Sie den unten stehenden Codeauszug in das Fenster ein und klicken Sie auf Execute (Ausführen).
// Add account and related contact
Account acct = new Account(
Name='SFDC Computing',
Phone='(415)555-1212',
NumberOfEmployees=50,
BillingCity='San Francisco');
insert 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 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 acct2;Verwenden des Abfrage-Editors
Die Entwicklerkonsole umfasst die Abfrage-Editor-Konsole, mit der Sie SOQL-Abfragen ausführen und die Ergebnisse anzeigen können. Der Abfrage-Editor bietet eine schnelle Möglichkeit zum Überprüfen der Datenbank. Dies ist eine gute Methode, Ihre SOQL-Abfragen zu testen, bevor Sie sie zu Ihrem Apex-Code hinzufügen. Wenn Sie den Abfrage-Editor verwenden, müssen Sie nur die SOQL-Anweisung ohne den umgebenden Apex-Code angeben.
Führen Sie folgendes SOQL-Beispiel aus:
- Klicken Sie in der Developer Console auf die Registerkarte Query Editor (Abfrage-Editor).
- Kopieren Sie den folgenden Code, fügen Sie ihn in das erste Feld unter "Query Editor" ein und klicken Sie dann auf Execute (Ausführen).
SELECT Name,Phone FROM Account
Alle Accountdatensätze in Ihrer Organisation werden im Abschnitt "Query Results" (Abfrageergebnisse) als Zeilen mit Feldern angezeigt.
Grundlegende SOQL-Syntax
Die Syntax einer grundlegenden SOQL-Abfrage sieht wie folgt aus:
SELECT fields FROM ObjectName [WHERE Condition]
Die WHERE-Klausel ist optional. Beginnen wir mit einer sehr einfachen Abfrage. Die folgende Abfrage beispielsweise ruft Accounts sowie für jeden Account die Felder "Name" und "Telefon" ab:
SELECT Name,Phone FROM Account
Die Abfrage besteht aus zwei Teilen:
-
SELECT Name,Phone: In diesem Teil werden die Felder aufgelistet, die abgerufen werden sollen. Die Felder werden nach dem Schlüsselwort SELECT in einer kommagetrennten Liste angegeben. Sie können auch nur ein Feld angeben, wobei kein Komma erforderlich ist (z. B. "SELECT Phone").
-
FROM Account: In diesem Teil wird das Standardobjekt oder benutzerdefinierte Objekt angegeben, das abgerufen werden soll. In diesem Beispiel handelt es sich um "Account". Für ein benutzerdefiniertes Objekts namens "Invoice_Statement" wird "Invoice_Statement__c" angegeben.
Über die Grundlagen hinaus
Im Gegensatz zu anderen SQL-Sprachen können Sie nicht "*" angeben, um alle Felder eines Objekts abzurufen. Verwenden Sie stattdessen das Schlüsselwort FIELDS(), um alle Standardfelder (FIELDS(STANDARD)), alle benutzerdefinierten Felder (FIELDS(CUSTOM)) oder allgemein alle Felder (FIELDS(ALL)) eines Objekts abzurufen. Weitere Informationen finden Sie unter SELECT in der SOQL and SOSL Reference.
Wenn Sie versuchen, auf ein Feld zuzugreifen, das Sie in der SELECT-Klausel nicht angegeben haben (entweder explizit oder mithilfe des Schlüsselworts FIELDS()), wird ein Fehler ausgegeben, da das Feld nicht abgerufen wurde.
Sie müssen das Id-Feld in der Abfrage nicht angeben, das es in Apex-Abfragen stets zurückgegeben wird, unabhängig davon, ob es in der Abfrage angegeben ist. Beispiel: "SELECT Id,Phone FROM Account" und "SELECT Phone FROM Account" sind synonyme Anweisungen. Das Id-Feld sollte jedoch angegeben werden, wenn es das einzige Feld ist, das Sie abrufen, da mindestens ein Feld aufgelistet werden muss: "SELECT Id FROM Account". Es empfiehlt sich auch, das Id-Feld beim Ausführen einer Abfrage im Abfrage-Editor anzugeben, da das Id-Feld nur angezeigt wird, wenn es angegeben ist.
Filtern von Abfrageergebnissen mit Bedingungen
Wenn in Ihrer Organisation mehr als ein Account vorhanden ist, werden alle zurückgegeben. Wenn nur solche Accounts zurückgegeben werden sollen, die eine bestimmte Bedingung erfüllen, können Sie diese Bedingung in die WHERE-Klausel einfügen. Mit dem folgenden Beispiel werden nur die Accounts abgerufen, deren Name "SFDC Computing" lautet. Beachten Sie, dass bei Vergleichen von Zeichenfolgen nicht zwischen Groß- und Kleinschreibung unterschieden wird.
SELECT Name,Phone FROM Account WHERE Name='SFDC Computing'
Die WHERE-Klausel kann mehrere Bedingungen enthalten, die mithilfe von logischen Operatoren (AND, OR) und Klammern gruppiert werden. Die folgende Abfrage beispielsweise gibt alle Accounts namens "SFDC Computing" zurück, die mehr als 25 Mitarbeiter haben:
SELECT Name,Phone FROM Account WHERE (Name='SFDC Computing' AND NumberOfEmployees>25)
Nachstehend folgt ein weiteres Beispiel mit einer komplexeren Bedingung. Diese Abfrage gibt alle diese Datensätze zurück:
- Alle Accounts namens "SFDC Computing" oder
- Alle Accounts mit mehr als 25 Mitarbeitern und Los Angeles als Stadt in der Rechnungsanschrift.
SELECT Name,Phone FROM Account WHERE (Name='SFDC Computing' OR (NumberOfEmployees>25 AND BillingCity='Los Angeles'))
Über die Grundlagen hinaus
Statt für den Vergleich den Gleichheitsoperator (=) zu verwenden, können Sie mit dem Operator LIKE unscharfe Abgleiche vornehmen. Mit folgender Bedingung können Sie beispielsweise alle Accounts abrufen, deren Name mit "SFDC" beginnt: WHERE Name LIKE 'SFDC%'. Das Platzhalterzeichen "%" gleicht beliebige Zeichen oder kein Zeichen ab. Das Zeichen "_" hingegen kann zum Abgleichen von nur einem Zeichen verwendet werden.
Anordnen von Abfrageergebnissen
Wenn eine Abfrage ausgeführt wird, gibt sie Datensätze aus Salesforce in willkürlicher Reihenfolge zurück, d. h., die Reihenfolge der Datensätze im zurückgegebenen Liste ist nicht jedes Mal gleich, wenn die Abfrage ausgeführt wird. Sie können die zurückgegebene Datensatzgruppe jedoch sortieren, indem Sie eine ORDER BY-Klausel einfügen und das Feld angeben, nach dem die Datensatzgruppe sortiert werden soll. Mit folgendem Beispiel werden alle abgerufenen Accounts nach dem Namensfeld sortiert.
SELECT Name,Phone FROM Account ORDER BY Name
Die standardmäßige Sortierreihenfolge ist alphabetisch, angegeben als "ASC". Die vorherige Anweisung entspricht Folgendem:
SELECT Name,Phone FROM Account ORDER BY Name ASC
Um die Reihenfolge umzukehren, verwenden Sie das Schlüsselwort DESC für absteigende Reihenfolge:
SELECT Name,Phone FROM Account ORDER BY Name DESC
Sie können nach den meisten Felder sortieren, einschließlich numerischen Feldern und Textfeldern. Eine Sortierung nach Feldern wie Rich-Text-Feldern oder Auswahllisten mit Mehrfachauswahl ist nicht möglich.
Probieren Sie diese SOQL-Anweisungen im Abfrage-Editor aus und beobachten Sie, wie sich die Reihenfolge der zurückgegebenen Datensätze basierend auf dem Namensfeld ändert.
Begrenzen der Anzahl der zurückgegebenen Datensätze
Sie können die Anzahl der zurückgegebenen Datensätze auf eine beliebige Zahl begrenzen, indem Sie die Klausel "LIMIT n" einfügen, wobei "n" für die Anzahl der Datensätze steht, die zurückgegeben werden soll. Das Begrenzen des Ergebnissatzes ist praktisch, wenn es keine Rolle für Sie spielt, welche Datensätze zurückgegeben werden, sondern Sie einfach nur mit einem Teil der Datensätze arbeiten möchten. Die folgende Abfrage beispielsweise ruft den ersten Account ab, der zurückgegeben wird. Beachten Sie, dass der zurückgegebene Wert bei Verwendung von LIMIT 1 ein Account und nicht eine Liste ist.
Account oneAccountOnly = [SELECT Name,Phone FROM Account LIMIT 1];
Kombinieren aller Teile
Sie können die optionalen Klauseln in einer Abfrage kombinieren, und zwar in folgender Reihenfolge:
SELECT Name,Phone FROM Account
WHERE (Name = 'SFDC Computing' AND NumberOfEmployees>25)
ORDER BY Name
LIMIT 10Führen Sie die folgende SOQL-Abfrage in Apex im Fenster für die anonyme Ausführung in der Entwicklerkonsole aus. Untersuchen Sie anschließend die Debug-Anweisungen im Debug-Protokoll. Es sollte ein Beispielaccount zurückgegeben werden.
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);Zugreifen auf Variablen in SOQL-Abfragen
SOQL-Anweisungen in Apex können Apex-Code-Variablen und -Ausdrücke referenzieren, wenn ihnen ein Doppelpunkt (:) vorangestellt ist. Die Verwendung einer lokalen Variablen in einer SOQL-Anweisung wird als Bindung bezeichnet.
Das folgende Beispiel zeigt, wie die Variable "targetDepartment" in der WHERE-Klausel verwendet wird.
String targetDepartment = 'Wingo';
Contact[] techContacts = [SELECT FirstName,LastName
FROM Contact WHERE Department=:targetDepartment];Abfragen zugehöriger Datensätze
Datensätze in Salesforce können über Beziehungen miteinander verknüpft werden: Nachschlagebeziehungen oder Master-Detail-Beziehungen. Kontakt weist beispielsweise eine Nachschlagebeziehung mit einem Account auf. Wenn Sie einen Kontakt erstellen oder aktualisieren, können Sie ihn einem Account zuordnen. Die Kontakte, die demselben Account zugeordnet sind, werden in einer Themenliste auf der Seite des Accounts angezeigt. Auf die gleiche Weise, wie Sie verknüpfte Datensätze auf der Salesforce-Benutzeroberfläche anzeigen können, können Sie verknüpfte Datensätze in SOQL abfragen.
Um mit einem übergeordneten Datensatz verknüpfte untergeordnete Datensätze abzurufen, fügen Sie für die untergeordneten Datensätze eine innere Abfrage hinzu. Die FROM-Klausel der inneren Abfrage wird für den Beziehungsnamen und nicht für einen Salesforce-Objektnamen ausgeführt. Das folgende Beispiel enthält eine innere Abfrage zum Abrufen aller Kontakte, die jedem zurückgegebenen Account zugeordnet sind. Die FROM-Klausel gibt als Beziehung "Contacts" an, die eine Standardbeziehung in Accounts ist und Accounts und Kontakte miteinander verknüpft.
SELECT Name, (SELECT LastName FROM Contacts) FROM Account WHERE Name = 'SFDC Computing'
Im nächsten Beispiel ist die SOQL-Beispielabfrage in Apex eingebettet und es wird gezeigt, wie die untergeordneten Datensätze aus dem SOQL-Ergebnis abgerufen werden, indem im sObject der Beziehungsname "Contacts" verwendet wird.
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);Mithilfe der Dot-Notation können Sie eine Beziehung von einem untergeordneten Objekt (Kontakt) zu einem Feld im übergeordneten Objekt (Account.Name) durchlaufen. Der folgende Apex-Codeauszug beispielsweise fragt Kontaktdatensätze mit dem Vornamen "Carol" ab und kann den Namen von Carols zugeordnetem Account abrufen, indem er die Beziehung zwischen Accounts und Kontakten durchläuft.
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);Abfragen von Datensätzen in Batches mithilfe von For-Schleifen in SOQL
Es mag naheliegend erscheinen, eine SOQL-Abfrage als Liste zu speichern und die Liste dann in Schleife zu durchlaufen, um alle Datensätze zu verarbeiten. Diese Transaktion ist jedoch ressourcenintensiv, besonders wenn die SOQL-Abfrage Tausende von Datensätzen zurückgibt. Wenn Sie in einer mandantenfähigen Umgebung wie Salesforce arbeiten, ist es wichtig, dass Sie die Ausführungsobergrenzen einhalten. Um die Heap-Grenze nicht zu überschreiten, verwenden Sie stattdessen eine For-Schleife in SOQL mit "variable_list". For-Schleifen in SOQL verwenden eine effiziente Segmentierungsmethode zum Abrufen von Datensätzen und haben folgende Syntax:
for (variable_list : [soql_query]) {
for (variable : variable_list) {
// Update records
}
update variable_list;
}"variable_list" muss müssen denselben Typ aufweisen wie die sObjects, die von "soql_query" zurückgegeben werden.
Bei diesem Format wird die äußere Schleife einmal für jeden Batch aus 200 sObjects ausgeführt, anstatt einmal pro Datensatz. Dieses Format ermöglicht die Massenaktualisierung von Datensätzen und die Durchführung von Massen-DML-Vorgängen, wodurch die Wahrscheinlichkeit verringert wird, die Heap-Grenze zu erreichen.
Hier ist ein Beispiel, das Sie mit Anonymous Apex ausführen können.
// 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);Ressourcen
- Salesforce Developers: SOQL and SOSL Reference
- Salesforce Developers: Execution Governors and Limits
- Salesforce Developers: For-Schleifen in SOQL
- Salesforce Developers: Working with Very Large SOQL Queries
