Écriture de requêtes SOQL
Objectifs de formation
Une fois cette unité terminée, vous pourrez :
- Écrire des requêtes SOQL en Apex
- Exécuter des requêtes SOQL en utilisant l'éditeur de requête de la Developer Console
- Exécuter des requêtes SOQL incorporées dans Apex en utilisant un Apex anonyme
- Interroger des enregistrements associés
Premiers pas avec la spécification SOQL
Pour lire un enregistrement depuis Salesforce, vous devez écrire une requête. Salesforce fournit le Salesforce Object Query Language, ou SOQL en abrégé, que vous pouvez utiliser pour lire des enregistrements sauvegardés. SOQL est semblable au langage SQL standard mais est personnalisé pour Lightning Platform.
Apex a un accès direct aux enregistrements Salesforce stockés dans la base de données. Par conséquent, vous pouvez incorporer des requêtes SOQL dans votre code Apex et obtenir des résultats de façon simple. Lorsqu’il est incorporé dans Apex, SOQL est appelé SOQL en ligne.
Pour inclure des requêtes SOQL dans votre code Apex, placez l'instruction SOQL entre crochets et attribuez la valeur renvoyée à un tableau de sObjects. Par exemple, la requête ci-dessous récupère tous les enregistrements de compte qui contiennent deux champs, Name (Nom) et Phone (Téléphone), et renvoie un tableau de sObjects Account (Compte).
Account[] accts = [SELECT Name,Phone FROM Account];
Prérequis
Certaines requêtes de cette unité supposent que l'organisation possède des comptes et des contacts. Avant d'exécuter les requêtes, créez quelques données exemple.
- Dans la Developer Console, ouvrez la fenêtre Execute Anonymous (Exécution anonyme) depuis le menu Debug (Débogage).
- Insérez l'extrait ci-dessous dans la fenêtre, puis cliquez sur Execute (Exécuter).
// 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;
Utilisation de l’éditeur de requête
La Developer Console fournit la console Query Editor (Éditeur de requête), qui permet d'exécuter des requêtes SOQL et d'afficher les résultats. L'éditeur de requête permet d'inspecter rapidement la base de données. Il est efficace pour tester les requêtes SOQL avant de les ajouter à un code Apex. Lorsque vous utilisez l'éditeur de requête, vous devez indiquer uniquement l'instruction SOQL, sans le code Apex qui l'entoure.
Essayons d'exécuter l'exemple SOQL suivant :
- Dans la Developer Console, cliquez sur l’onglet Query Editor (Éditeur de requête).
- Copiez et collez l'élément ci-dessous dans la première zone sous Query Editor (Éditeur de requête), puis cliquez sur Execute (Exécuter).
SELECT Name,Phone FROM Account
Tous les enregistrements de compte de votre organisation s’affichent dans la section Query Results (Résultats de requête), sous forme de lignes avec des champs.
Syntaxe SOQL de base
La syntaxe d'une requête SOQL de base est la suivante :
SELECT fields FROM ObjectName [WHERE Condition]
La clause WHERE est facultative. Commençons avec une requête très simple. Par exemple, la requête suivante récupère les comptes et obtient les champs Name (Nom) et Phone (Téléphone) pour chaque compte.
SELECT Name,Phone FROM Account
La requête comporte deux parties :
-
SELECT Name,Phone
: cette partie répertorie les champs que vous souhaitez récupérer. Les champs sont spécifiés après le mot-clé SELECT dans une liste de valeurs séparées une virgule. Vous pouvez également spécifier un seul champ, auquel cas la virgule n’est pas nécessaire (p. ex.SELECT Phone
).
-
FROM Account
: cette partie spécifie l'objet standard ou personnalisé que vous souhaitez récupérer. Dans cet exemple, l'objet est Account (Compte). Pour un objet personnalisé appelé Releve_Factures, il correspond à Releve_Factures__c.
Filtrage des résultats de requête avec des conditions
Si l'organisation possède plusieurs comptes, ils sont tous renvoyés. Pour limiter les comptes renvoyés en fonction d'une condition particulière, vous pouvez ajouter cette condition dans la clause WHERE. L'exemple ci-dessous récupère uniquement les comptes qui portent le nom SFDC Computing. Notez que les comparaisons dans les chaînes sont insensibles à la casse.
SELECT Name,Phone FROM Account WHERE Name='SFDC Computing'
La clause WHERE peut contenir plusieurs conditions qui sont regroupées à l'aide d'opérateurs logiques (AND, OR) et de parenthèses. Par exemple, la requête suivante renvoie tous les comptes portant le nom SFDC Computing et comptant plus de 25 employés :
SELECT Name,Phone FROM Account WHERE (Name='SFDC Computing' AND NumberOfEmployees>25)
Voici un autre exemple avec une condition plus complexe. Cette requête renvoie tous ces enregistrements :
- Tous les comptes SFDC Computing
- Tous les comptes de plus de 25 employés dont la ville de facturation est Los Angeles
SELECT Name,Phone FROM Account WHERE (Name='SFDC Computing' OR (NumberOfEmployees>25 AND BillingCity='Los Angeles'))
Classement des résultats de requête
Lorsqu'elle est exécutée, une requête renvoie des enregistrements issus de Salesforce sans ordre particulier. Par conséquent, vous ne pouvez compter sur un classement régulier des enregistrements dans le tableau à chaque exécution de la requête. Vous pouvez cependant trier l'ensemble d'enregistrements renvoyé en ajoutant une clause ORDER BY et en spécifiant le champ par lequel l'ensemble d'enregistrements doit être classé. Cet exemple trie tous les enregistrements récupérés en fonction du champ Name (Nom).
SELECT Name,Phone FROM Account ORDER BY Name
L'ordre de tri par défaut est l'ordre alphabétique, spécifié par ASC (ascendant). L'instruction précédente est équivalente à ce qui suit :
SELECT Name,Phone FROM Account ORDER BY Name ASC
Pour inverser l'ordre de tri, utilisez le mot-clé DESC (descendant) :
SELECT Name,Phone FROM Account ORDER BY Name DESC
Vous pouvez trier la plupart des champs, y compris les champs numériques et de texte. Vous ne pouvez pas réaliser de tri sur des champs tels que ceux contenant du texte enrichi ou sur des listes de multi-sélections.
Essayez ces instructions SOQL dans l'éditeur de requête et constatez comment l’ordre des enregistrement renvoyés est modifié en fonction du champ Name (Nom).
Limitation du nombre d’enregistrements renvoyés
Vous pouvez limiter le nombre d'enregistrements renvoyés à une valeur arbitraire en ajoutant la clause LIMIT n
, où n est le nombre d'enregistrements renvoyés voulu. La limitation de l'ensemble d'enregistrements est pratique lorsque vous souhaitez travailler avec un sous-ensemble d'enregistrements quelconque, sans vous soucier du choix des enregistrements. Par exemple, la requête ci-dessous récupère le premier compte qui est renvoyé. Notez que la valeur renvoyée est un compte, pas un tableau, lors de l'utilisation de LIMIT 1
.
Account oneAccountOnly = [SELECT Name,Phone FROM Account LIMIT 1];
Combinaison de l’ensemble des éléments
Vous pouvez combiner les clauses facultatives dans une requête, dans l'ordre suivant :
SELECT Name,Phone FROM Account WHERE (Name = 'SFDC Computing' AND NumberOfEmployees>25) ORDER BY Name LIMIT 10
Exécutez la requête SOQL ci-dessous dans Apex en utilisant la fenêtre Execute Anonymous (Exécution anonyme) de la Developer Console. Inspectez ensuite les instructions de débogage dans le journal de débogage. Un exemple de compte doit être renvoyé.
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 array info System.debug(accts);
Accès à des variables dans des requêtes SOQL
Les instructions SOQL dans Apex peuvent référencer des variables et des expressions de code Apex si elles sont précédées par un signe deux-points (:). L'utilisation d'une variable locale dans une instruction SOQL est appelée liaison.
Cet exemple montre comment utiliser la variable targetDepartment
dans la clause WHERE.
String targetDepartment = 'Wingo'; Contact[] techContacts = [SELECT FirstName,LastName FROM Contact WHERE Department=:targetDepartment];
Interrogation d’enregistrements associés
Dans Salesforce, les enregistrements peuvent être liés par des relations : il peut s’agir de relations de référence ou de relations principal-détail. Par exemple, Contact (Contact) a une relation de référence avec Account (Compte). Lorsque vous créez ou mettez à jour un contact, vous pouvez l'associer à un compte. Les contacts qui sont associés au même compte sont affichés dans une liste associée de la page du compte. De même que vous pouvez afficher des enregistrements associés dans l'interface utilisateur de Salesforce, vous pouvez interroger des enregistrements associés dans SOQL.
Pour obtenir les enregistrements enfants associés à un enregistrement parent, ajoutez une requête interne pour les enregistrements enfants. La clause FROM de la requête interne est exécutée sur le nom de la relation au lieu du nom d'objet Salesforce. L'exemple ci-dessous contient une requête interne afin d'obtenir tous les contacts associés à chaque compte renvoyé. La clause FROM spécifie la relation Contacts (Contacts), une relation par défaut avec Account (Compte) qui lie les comptes et les contacts.
SELECT Name, (SELECT LastName FROM Contacts) FROM Account WHERE Name = 'SFDC Computing'
L'exemple ci-dessous incorpore l'exemple de requête SOQL dans Apex et montre comment obtenir les enregistrements enfants depuis le résultat SOQL en utilisant le nom de relation Contacts dans le sObject.
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);
Vous pouvez traverser une relation depuis un objet enfant (contact) vers un champ dans son parent (Account.Name) à l'aide d'une notation pointée. Par exemple, l'extrait Apex ci-dessous interroge les enregistrements de contact dont le prénom est Carol, et peut récupérer le compte associé au nom Carol en traversant la relation entre les comptes et les contacts.
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);
Interrogation d’enregistrements dans des lots à l’aide de boucles For SOQL
Avec une boucle for SOQL, vous pouvez inclure une requête SOQL dans une boucle for
. Les résultats d'une requête SOQL peuvent être itérés dans la boucle. Les boucles for SOQL utilisent une méthode différente pour récupérer des enregistrements : ils sont récupérés à l'aide d'une segmentation efficace avec des appels à la requête et des méthodes queryMore de l'API SOAP. L'utilisation de boucles for SOQL permet de ne pas atteindre la limitation en taille de segment.
Les boucles for
SOQL itèrent sur tous les enregistrements de sObject renvoyés par une requête SOQL. La syntaxe d’une boucle for
SOQL est :
for (variable : [soql_query]) { code_block }
ou
for (variable_list : [soql_query]) { code_block }
variable
et variable_list
doivent être de même type que les sObjects renvoyés par soql_query
.
Il est préférable d'utiliser le format de liste sObject des boucles for SOQL, car la boucle est exécutée une fois pour chaque lot de 200 sObjects. Cela permet d'utiliser des lots d'enregistrements et d'effectuer des opérations DML par lot pour ne pas atteindre les limitations du gouverneur.
insert new 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[] tmp : [SELECT Id FROM Account WHERE Name LIKE 'for loop _']) { j = tmp.size(); i++; } System.assertEquals(3, j); // The list should have contained the three accounts // named 'yyy' System.assertEquals(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
Ressources