Suivez votre progression
Accueil Trailhead
Accueil Trailhead

É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

Écriture de requêtes 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 similaire 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 ont deux champs, Nom et Téléphone, et renvoie un tableau de sObjects 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.

  1. Dans la Developer Console, ouvrez la fenêtre Execute Anonymous depuis le menu Debug.
  2. Insérez l'extrait ci-dessous dans la fenêtre, puis cliquez sur Exécute.
// 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 de l'é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 :

  1. Dans la Developer Console, cliquez sur l'onglet Query Editor.
  2. Copiez et collez l'élément ci-dessous dans la première case, sous l'éditeur de requête, puis cliquez sur Execute.
SELECT Name,Phone FROM Account

Tous les enregistrements de compte de votre organisation s'affichent dans la section 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 des comptes et obtient deux champs pour chaque compte : le champ ID et le champ Téléphone.

SELECT Name,Phone FROM Account

La requête comporte deux parties :

  1. 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).
  2. FROM Account : Cette partie spécifie l'objet standard ou personnalisé que vous souhaitez récupérer. Dans cet exemple, l'objet est Compte. Pour un objet personnalisé appelé Releve_Factures, il correspond à Releve_Factures__c.

Au-delà des bases

Contrairement aux autres langages SQL, vous ne pouvez pas spécifier d'astérisque (*) pour tous les champs. Vous devez spécifier explicitement chaque champ souhaité. Si vous essayez d'accéder à un champ que vous n'avez pas spécifié dans la clause SELECT, vous obtenez une erreur, car le champ n'a pas été récupéré.

Il n'est pas nécessaire de spécifier le champ ID dans la requête, car il est toujours renvoyé dans les requêtes Apex, qu'il soit spécifié ou non. Par exemple : SELECT Id,Phone FROM Account et SELECT Phone FROM Account sont des instructions équivalentes. Vous pouvez spécifier le champ ID s'il correspond au seul champ récupéré, car vous devez répertorier au moins un champ : SELECT Id FROM Account. Vous pouvez également spécifier le champ ID lors de l'exécution d'une requête dans l'éditeur de requête, car le champ est affiché uniquement s'il est spécifié.

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 les comptes SFDC Computing, ou tous les comptes avec 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'))

Au-delà des bases

Au lieu d'utiliser l'opérateur égal à (=) pour la comparaison, vous pouvez effectuer des correspondances partielles à l'aide de l'opérateur LIKE. Par exemple, vous pouvez récupérer tous les comptes dont le nom commence par SFDC en utilisant cette condition : WHERE Name LIKE 'SFDC%'. Le caractère générique % correspond à tous les caractères ou à aucun. Par contre, le caractère _ peut être utilisé pour correspondre à un seul caractère.

Classement des résultats de requête

Lorsqu'elle est exécutée, une requête renvoie les enregistrements 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 par le champ 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 à :

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 trier 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 examinez les modifications d'enregistrements renvoyées organisées par le champ 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 toutes les pièces

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 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 deux point (:). 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 : relations de référence ou relations principal-détail. Par exemple, Contact a une relation de référence avec 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 de Contacts, une relation par défaut avec 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);
Remarque

Remarque

Les exemples de cette section sont basés sur des objets standard. Les objets personnalisés peuvent également être liés par des relations personnalisées. Les noms de relation personnalisée ont un suffixe en __r. Par exemple, les relevés de facture sont liés à des éléments de ligne via la relation Line_Items__r dans l'objet personnalisé Invoice_Statement__c

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