Scrivere query SOQL
Obiettivi di apprendimento
Iniziare a utilizzare SOQL
Account[] accts = [SELECT Name,Phone FROM Account];
Prerequisiti
Alcune query di questa unità prevedono che l'organizzazione disponga di account e referenti. Prima di eseguire le query, bisogna creare dei dati di esempio.
- Nella Developer Console, apri la finestra Execute Anonymous (Esecuzione anonima) nel menu Debug.
- Inserisci nella finestra lo snippet riportato di seguito e fai clic su Execute (Esegui).
// 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;
Utilizzare Query Editor
La Developer Console offre la console Query Editor, che permette di eseguire le query SOQL e visualizzare i risultati. Query Editor è uno strumento che consente di ispezionare rapidamente il database. È un valido strumento per testare le query SOQL prima di aggiungerle al codice Apex. Quando si utilizza Query Editor, è necessario fornire solo l'istruzione SOQL senza il codice Apex in cui è inserita.
Proviamo a eseguire il seguente esempio di SOQL:
- Nella Developer Console, fai clic sulla scheda Query Editor.
- Copia e incolla quanto segue nella prima casella di Query Editor, quindi fai clic su Execute (Esegui).
SELECT Name,Phone FROM Account
Tutti i record degli account dell'organizzazione sono visualizzati nella sezione Query Results (Risultati della query) come righe con campi.
Sintassi SOQL di base
Questa è la sintassi di una query SOQL di base:
SELECT fields FROM ObjectName [WHERE Condition]
La clausola WHERE è facoltativa. Iniziamo con una query molto semplice. Ad esempio, la query seguente recupera gli account e ottiene i campi Name e Phone per ciascuno di essi.
SELECT Name,Phone FROM Account
La query si compone di due parti:
-
SELECT Name,Phone
: questa parte riporta i campi che si vogliono recuperare. I campi sono specificati dopo la parola chiave SELECT in un elenco delimitato da virgole. In alternativa, è possibile specificare un solo campo, nel qual caso non è necessaria la virgola (ad es.SELECT Phone
). -
FROM Account
: questa parte specifica l'oggetto standard o personalizzato che si vuole recuperare. In questo esempio, si tratta di Account. Per un oggetto personalizzato chiamato Estratto_conto, sarebbe Estratto_conto__c.
Filtrare i risultati delle query con le condizioni
Se nell'organizzazione ci sono più account, verranno restituiti tutti. Se desideri limitare gli account restituiti a quelli che soddisfano una determinata condizione, puoi aggiungere tale condizione all'interno della clausola WHERE. Nell'esempio riportato di seguito vengono recuperati solo gli account il cui nome è SFDC Computing. Tieni presente che i confronti tra stringhe non fanno distinzione tra maiuscole e minuscole.
SELECT Name,Phone FROM Account WHERE Name='SFDC Computing'
La clausola WHERE può contenere più condizioni che vengono raggruppate utilizzando gli operatori logici (AND, OR) e le parentesi. Ad esempio, questa query restituisce tutti gli account il cui nome è SFDC Computing e che hanno più di 25 dipendenti:
SELECT Name,Phone FROM Account WHERE (Name='SFDC Computing' AND NumberOfEmployees>25)
Ecco un altro esempio con una condizione più complessa. Questa query restituisce tutti questi record:
- Tutti gli account SFDC Computing
- Tutti gli account con più di 25 dipendenti la cui città di fatturazione è Los Angeles
SELECT Name,Phone FROM Account WHERE (Name='SFDC Computing' OR (NumberOfEmployees>25 AND BillingCity='Los Angeles'))
Ordinare i risultati delle query
Quando una query viene eseguita, restituisce i record da Salesforce senza un ordine particolare, quindi non puoi fare affidamento sul fatto che l'ordine dei record nell'array restituito sia lo stesso ogni volta che la query viene eseguita. Tuttavia, puoi scegliere di ordinare l'insieme di record restituiti aggiungendo una clausola ORDER BY e specificando il campo in base al quale l'insieme di record deve essere ordinato. In questo esempio tutti gli account recuperati vengono ordinati in base al campo Name.
SELECT Name,Phone FROM Account ORDER BY Name
L'ordinamento predefinito è quello alfabetico, specificato come ASC. L'istruzione precedente è equivalente a:
SELECT Name,Phone FROM Account ORDER BY Name ASC
Per invertire l'ordine, usa la parola chiave DESC per indicare l'ordine discendente:
SELECT Name,Phone FROM Account ORDER BY Name DESC
È possibile ordinare la maggior parte dei campi, compresi quelli numerici e testuali. Non è possibile ordinare i campi come il testo RTF e gli elenchi di selezione a selezione multipla.
Prova queste istruzioni SOQL in Query Editor e osserva come cambia l'ordine dei record restituiti in base al campo Name.
Limitare il numero di record restituiti
È possibile limitare il numero di record restituiti a un numero arbitrario aggiungendo la clausola LIMIT n
, dove n è il numero di record che si desidera vengano restituiti. Limitare l'insieme dei risultati torna utile quando non interessa quali record vengono restituiti, ma si desidera lavorare solo con un sottoinsieme di record. Ad esempio, questa query recupera il primo account che viene restituito. Com'è possibile notare, il valore restituito è un solo account e non un array quando si utilizza la clausola LIMIT 1
.
Account oneAccountOnly = [SELECT Name,Phone FROM Account LIMIT 1];
Combinare tutti gli elementi
È possibile mettere insieme le clausole opzionali in un'unica query, nel seguente ordine:
SELECT Name,Phone FROM Account WHERE (Name = 'SFDC Computing' AND NumberOfEmployees>25) ORDER BY Name LIMIT 10
Esegui in Apex la query SOQL riportata di seguito, utilizzando la finestra Execute Anonymous (Esecuzione anonima) della Developer Console. Quindi controlla le istruzioni di debug nel registro di debug. Dovrebbe essere restituito un solo account di esempio.
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);
Accedere alle variabili nelle query SOQL
Le istruzioni SOQL in Apex possono fare riferimento a variabili ed espressioni di codice Apex se sono precedute dai due punti (:). Il ricorso a una variabile locale all'interno di un'istruzione SOQL si chiama bind.
Questo esempio mostra come utilizzare la variabile targetDepartment
nella clausola WHERE.
String targetDepartment = 'Wingo'; Contact[] techContacts = [SELECT FirstName,LastName FROM Contact WHERE Department=:targetDepartment];
Eseguire query su record correlati
I record in Salesforce possono essere collegati tra loro attraverso relazioni: relazioni di ricerca o relazioni record principale-record dettaglio. Ad esempio, il Referente ha una relazione di ricerca con l'Account. Quando si crea o si aggiorna un referente, è possibile associarlo a un account. I referenti associati allo stesso account vengono visualizzati in un elenco correlato nella pagina dell'account. Così come puoi visualizzare i record correlati nell'interfaccia utente di Salesforce, allo stesso modo puoi eseguire query su record correlati in SOQL.
Per recuperare i record secondari correlati a un record principale, aggiungi una query interna per i record secondari. La clausola FROM della query interna viene eseguita in base al nome della relazione, anziché al nome dell'oggetto Salesforce. Questo esempio contiene una query interna per ottenere tutti i referenti associati a ciascun account restituito. La clausola FROM specifica la relazione Contacts, una relazione predefinita su Account che collega account e referenti.
SELECT Name, (SELECT LastName FROM Contacts) FROM Account WHERE Name = 'SFDC Computing'
Nel prossimo esempio, incorporiamo la query SOQL di esempio in Apex e mostriamo come ottenere i record secondari dal risultato SOQL utilizzando il nome della relazione Contacts dell'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);
È possibile attraversare una relazione da un oggetto secondario (Contact) a un campo del rispettivo oggetto principale (Account.Name) utilizzando la notazione con punti. Ad esempio, il seguente snippet Apex esegue una query sui record dei referenti il cui nome è Carol ed è in grado di recuperare il nome dell'account associato a Carol attraversando la relazione tra account e referenti.
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);
Eseguire query su record in batch utilizzando i loop for SOQL
Con un loop for SOQL, è possibile includere una query SOQL all'interno del loop for
. L'iterazione dei risultati di una query SOQL può avvenire all'interno del loop. I loop for SOQL utilizzano un metodo diverso per recuperare i record: i record vengono recuperati utilizzando una suddivisione in blocchi efficiente con chiamate ai metodi query e queryMore dell'API SOAP. Utilizzando i loop for SOQL, è possibile evitare di raggiungere il limite delle dimensioni dell'heap.
for
SOQL avviene su tutti i record sObject restituiti da una query SOQL. La sintassi di un loop for
SOQL è una delle seguenti:for (variable : [soql_query]) { code_block }
for (variable_list : [soql_query]) { code_block }
Sia variable
che variable_list
devono essere dello stesso tipo degli sObject restituiti dalla soql_query
.
È preferibile utilizzare il formato dell'elenco sObject del loop for SOQL, in quanto il loop viene eseguito una sola volta per ogni batch di 200 sObject. In questo modo è possibile lavorare su batch di record ed eseguire operazioni DML in batch, evitando così di raggiungere i limiti del governor.
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