Skip to main content

Manipolare i record con DML

Obiettivi di apprendimento

Al completamento di questa unità, sarai in grado di:

  • Utilizzare DML per inserire, aggiornare ed eliminare i record.
  • Eseguire istruzioni DML in blocco.
  • Utilizzare upsert per inserire o aggiornare un record.
  • Generare un'eccezione DML.
  • Utilizzare un metodo Database per inserire nuovi record con l'opzione di esito parziale ed elaborare i risultati.
  • Sapere quando utilizzare le istruzioni DML e quando utilizzare i metodi Database.
  • Eseguire operazioni DML su record correlati.
Nota

Nota

Stai seguendo la formazione in italiano? Inizia la sfida in un Trailhead Playground in italiano e utilizza le traduzioni fornite tra parentesi per la navigazione. Per quanto riguarda i valori da inserire, copia e incolla solo quelli in lingua inglese, perché la convalida della sfida è basata sul fatto che i dati siano in inglese. Se non superi la sfida nella tua organizzazione italiana, ti consigliamo di (1) selezionare Stati Uniti per le impostazioni internazionali, (2) selezionare Inglese per la lingua seguendo le istruzioni riportate qui e, successivamente, (3) fare nuovamente clic sul pulsante "Controlla la sfida".

Visita il badge Trailhead nella tua lingua per informazioni dettagliate su come usufruire dell'esperienza Trailhead in altre lingue.

Manipolare i record con DML

È possibile creare e modificare i record in Salesforce utilizzando il Data Manipulation Language (DML), ovvero il linguaggio per la manipolazione dei dati. Il DML offre un modo semplice per gestire i record, attraverso semplici istruzioni per inserirli, aggiornarli, unirli, cancellarli e ripristinarli.

Apex è un linguaggio incentrato sui dati che viene salvato su Lightning Platform e ha pertanto un accesso diretto ai dati in Salesforce. A differenza di altri linguaggi di programmazione che richiedono una configurazione aggiuntiva per connettersi alle origini dati, con Apex DML la gestione dei record è facilissima! Utilizzando le istruzioni DML, puoi eseguire rapidamente operazioni sui tuoi record Salesforce. In questo esempio, l'account Acme viene aggiunto a Salesforce. Per prima cosa viene creato un sObject Account, che viene successivamente passato come argomento all'istruzione insert, che salva in modo permanente il record in Salesforce.

// Create the account sObject
Account acct = new Account(Name='Acme', Phone='(415)555-1212', NumberOfEmployees=100);
// Insert the account by using DML
insert acct;

Istruzioni DML

Queste sono le istruzioni DML disponibili.

  • insert
  • update
  • upsert
  • delete
  • undelete
  • merge

Ciascuna istruzione DML accetta un singolo sObject oppure un elenco (o un array) di sObject. Operare su un elenco di sObject è un modo più efficiente per elaborare i record.

Tutte queste istruzioni, tranne un paio, sono operazioni di database ben note. Le istruzioni upsert e merge sono specifiche di Salesforce e possono essere molto utili.

L'operazione DML upsert crea nuovi record e aggiorna i record sObject con una singola istruzione, utilizzando un campo specificato per determinare la presenza di oggetti esistenti oppure il campo ID se non è specificato alcun campo.

L'istruzione merge unisce fino a tre record dello stesso tipo sObject in uno solo dei record, eliminando gli altri e ristabilendo i rapporti principale-secondario tra tutti i record correlati.

Campo ID assegnato automaticamente ai nuovi record

Quando si inseriscono i record, il sistema assegna un ID a ciascun record. Oltre al salvataggio del valore dell'ID nel database in modo permanente, il valore dell'ID viene inoltre compilato automaticamente nella variabile sObject utilizzata come argomento nella chiamata DML.

Questo esempio mostra come ottenere l'ID nell'oggetto sObject che corrisponde all'account inserito.

// Create the account sObject
Account acct = new Account(Name='Acme', Phone='(415)555-1212', NumberOfEmployees=100);
// Insert the account by using DML
insert acct;
// Get the new ID on the inserted sObject argument
ID acctID = acct.Id;
// Display this ID in the debug log
System.debug('ID = ' + acctID);
// Debug log result (the ID will be different in your case)
// DEBUG|ID = 001D000000JmKkeIAF







Nota

Oltre i concetti di base

Poiché nell'esempio la variabile sObject contiene l'ID dopo la chiamata DML, è possibile riutilizzare questa variabile sObject per eseguire altre operazioni DML, ad esempio gli aggiornamenti, in quanto il sistema sarà in grado di mappare la variabile sObject al record corrispondente attraverso un abbinamento con l'ID.

È possibile recuperare un record dal database per ottenerne i campi, ivi compreso il campo ID, ma ciò non è possibile con il DML. È necessario scrivere una query utilizzando il SOQL. Studierai il SOQL in un'altra unità.

DML in blocco

È possibile eseguire operazioni DML sia su un singolo sObject sia in blocco su un elenco di sObject. L'esecuzione di operazioni DML in blocco è il metodo consigliato perché consente di evitare di superare i limiti del governor, ad esempio il limite DML di 150 istruzioni per transazione Apex. Questo limite è stato fissato per garantire un accesso equo alle risorse su Lightning Platform. L'esecuzione di un'operazione DML su un elenco di sObject conta come un'unica istruzione DML, non come un'istruzione per ogni sObject.

In questo esempio i referenti vengono inseriti in blocco utilizzando un elenco di referenti in un'unica chiamata. Nell'esempio, i referenti vengono anche aggiornati in blocco.

  1. Esegui questo snippet nella Developer Console utilizzando l'esecuzione Apex anonima.
    // Create a list of contacts
    List<Contact> conList = new List<Contact> {
        new Contact(FirstName='Joe',LastName='Smith',Department='Finance'),
            new Contact(FirstName='Kathy',LastName='Smith',Department='Technology'),
            new Contact(FirstName='Caroline',LastName='Roth',Department='Finance'),
            new Contact(FirstName='Kim',LastName='Shain',Department='Education')};
    // Bulk insert all contacts with one DML call
    insert conList;
    // List to hold the new contacts to update
    List<Contact> listToUpdate = new List<Contact>();
    // Iterate through the list and add a title only
    //   if the department is Finance
    for(Contact con : conList) {
        if (con.Department == 'Finance') {
            con.Title = 'Financial analyst';
            // Add updated contact sObject to the list.
            listToUpdate.add(con);
        }
    }
    // Bulk update all contacts with one DML call
    update listToUpdate;
  2. Ispeziona i referenti creati di recente nell'organizzazione.
    Il titolo specificato per due dei referenti del reparto finanziario dovrebbe essere Financial analyst (Analista finanziario).

Esecuzione di upsert su record

Se esiste un elenco contenente un misto di record nuovi ed esistenti, è possibile elaborare gli inserimenti e gli aggiornamenti di tutti i record dell'elenco utilizzando l'istruzione upsert. Upsert consente di evitare la creazione di record duplicati e può permettere di risparmiare tempo perché elimina la necessità di determinare preventivamente quali record esistono.

L'istruzione upsert abbina gli sObject ai record esistenti confrontando i valori di un solo campo. Se non si specifica un campo quando si chiama questa istruzione, upsert utilizza l'ID dell'sObject per abbinarlo ai record esistenti in Salesforce. In alternativa, è possibile specificare un campo da utilizzare per l'abbinamento. Per gli oggetti personalizzati, occorre specificare un campo personalizzato contrassegnato come ID esterno. Per gli oggetti standard, è possibile specificare qualsiasi campo la cui proprietà idLookup sia impostata su true. Ad esempio, la proprietà idLookup del campo Email dell'oggetto Contact o User è impostata. Per verificare le proprietà di un campo, consulta la guida di riferimento agli oggetti per Salesforce e Lightning Platform.

Sintassi dell'istruzione upsert

upsert sObject | sObject[]


upsert sObject | sObject[] field

Il campo opzionale è il token di un campo. Ad esempio, per specificare il campo MyExternalID, l'istruzione è:

upsert sObjectList Account.Fields.MyExternalId;

Upsert utilizza la chiave primaria del record sObject (l'ID), un campo idLookup o un campo ID esterno per determinare se creare un nuovo record o aggiornarne uno esistente:

  • Se non viene trovata una corrispondenza per la chiave, viene creato un nuovo record oggetto.
  • Se viene trovata una sola corrispondenza per la chiave, il record dell'oggetto esistente viene aggiornato.
  • Se vengono trovate più corrispondenze per la chiave, viene generato un errore e il record dell'oggetto non viene né inserito né aggiornato.

Questo esempio mostra come upsert aggiorna un record referente esistente e inserisce un nuovo referente in un'unica chiamata. Questa chiamata upsert aggiorna il referente esistente Josh e inserisce un nuovo referente, Kathy.

Nota

Nota

La chiamata upsert utilizza l'ID per abbinare il primo referente. La variabile josh viene riutilizzata per la chiamata upsert. Questa variabile è già stata popolata con l'ID record della precedente chiamata insert, pertanto in questo esempio non è necessario impostare esplicitamente l'ID.

  1. Esegui questo snippet nella finestra Execute Anonymous (Esecuzione anonima) della Developer Console.
    // Insert the Josh contact
    Contact josh = new Contact(FirstName='Josh',LastName='Kaplan',Department='Finance');
    insert josh;
    // Josh's record has been inserted
    //   so the variable josh has now an ID
    //   which will be used to match the records by upsert
    josh.Description = 'Josh\'s record has been updated by the upsert operation.';
    // Create the Kathy contact, but don't persist it in the database
    Contact kathy = new Contact(FirstName='Kathy',LastName='Brown',Department='Technology');
    // List to hold the new contacts to upsert
    List<Contact> contacts = new List<Contact> { josh, kathy };
    // Call upsert
    upsert contacts;
    // Result: Josh is updated and Kathy is created.
  2. Ispeziona tutti i referenti dell'organizzazione.
    Nella tua organizzazione ci sarà un solo record per Josh Kaplan, non due, perché l'operazione upsert ha trovato il record esistente e lo ha aggiornato anziché creare un nuovo record Contact (Referente). Sarà presente anche un solo record referente per Kathy Brown.

In alternativa, è possibile specificare un campo da utilizzare per l'abbinamento dei record. Questo esempio usa il campo Email dell'oggetto Contact (Referente) perché la sua proprietà idLookup è impostata. L'esempio inserisce il referente Jane Smith, crea un secondo sObject di tipo Contact, lo compila con la stessa email, quindi chiama upsert per aggiornare il referente utilizzando il campo email per la corrispondenza.

Nota

Nota

In questo esempio, se anziché upsert fosse stato usato insert, sarebbe stato inserito un duplicato del referente Jane Smith.

  1. Esegui questo snippet nella finestra Execute Anonymous (Esecuzione anonima) della Developer Console.
    Contact jane = new Contact(FirstName='Jane',
                             LastName='Smith',
                             Email='jane.smith@example.com',
                             Description='Contact of the day');
    insert jane;
    // 1. Upsert using an idLookup field
    // Create a second sObject variable.
    // This variable doesn’t have any ID set.
    Contact jane2 = new Contact(FirstName='Jane',
                             LastName='Smith',
                             Email='jane.smith@example.com',
                             Description='Prefers to be contacted by email.');
    // Upsert the contact by using the idLookup field for matching.
    upsert jane2 Contact.fields.Email;
    // Verify that the contact has been updated
    System.assertEquals('Prefers to be contacted by email.',
                       [SELECT Description FROM Contact WHERE Id=:jane.Id].Description);
  2. Ispeziona tutti i referenti dell'organizzazione.
    Nell'organizzazione ci sarà solo un referente Jane Smith la cui descrizione è stata aggiornata.

Eliminare i record

Puoi eliminare i record salvati in modo permanente utilizzando l'istruzione delete. I record eliminati non vengono eliminati definitivamente da Lightning Platform, ma rimangono nel Cestino per 15 giorni, periodo durante il quale possono essere ripristinati.

Questo esempio mostra come eliminare tutti i referenti il cui cognome è Smith. Se hai eseguito l'esempio del DML in blocco, l'organizzazione dovrebbe già contenere due referenti con il cognome Smith. Esegui questo snippet nella Developer Console utilizzando l'esecuzione Apex anonima, quindi verifica che non ci siano più referenti con il cognome Smith.

Contact[] contactsDel = [SELECT Id FROM Contact WHERE LastName='Smith'];
delete contactsDel;
Nota

Nota

Questo snippet include una query per recuperare i referenti (una query SOQL). Approfondirai il SOQL in un'altra unità.

Eccezioni delle istruzioni DML

Se durante un'operazione DML si verifica un errore, viene restituita un'eccezione di tipo DmlException. Per gestire le condizioni di errore, puoi intercettare le eccezioni nel tuo codice.

Questo esempio produce una DmlException perché tenta di inserire un account privo del campo obbligatorio Name. L'eccezione viene intercettata nel blocco catch.

try {
    // This causes an exception because
    //   the required Name field is not provided.
    Account acct = new Account();
    // Insert the account
    insert acct;
} catch (DmlException e) {
    System.debug('A DML exception has occurred: ' +
                e.getMessage());
}



Metodi Database

Apex contiene la classe Database integrata, in cui sono presenti metodi che eseguono operazioni DML e corrispondono alle loro controparti in DML.

Questi metodi Database sono statici e vengono richiamati utilizzando il nome della classe.

  • Database.insert()
  • Database.update()
  • Database.upsert()
  • Database.delete()
  • Database.undelete()
  • Database.merge()

A differenza delle istruzioni DML, i metodi Database dispongono del parametro facoltativo allOrNone che permette di specificare se l'operazione può riuscire parzialmente. Quando questo parametro è impostato su false, qualora dovessero verificarsi degli errori su un insieme parziale di record, il commit dei record senza errori verrà eseguito, mentre per i record con errori verranno restituiti gli errori. Inoltre, con l'opzione di riuscita parziale non vengono generate eccezioni.

Ecco come chiamare il metodo insert con allOrNone impostato su false.

Database.insert(recordList, false);

I metodi Database restituiscono oggetti risultato contenenti informazioni sulla presenza o meno di errori per ciascun record. Ad esempio, le operazioni insert e update restituiscono ciascuna un array di oggetti Database.SaveResult.

Database.SaveResult[] results = Database.insert(recordList, false);
Nota

Nota

Upsert restituisce oggetti Database.UpsertResult mentre delete restituisce oggetti Database.DeleteResult.

Per impostazione predefinita, il parametro allOrNone è true, il che significa che il metodo della classe Database si comporta come la relativa controparte nell'istruzione DML e genera un'eccezione se si verifica un errore.

Le due istruzioni seguenti equivalgono all'istruzione insert recordList;.

Database.insert(recordList);

E:

Database.insert(recordList, true);







Nota

Oltre i concetti di base

Oltre a questi metodi, la classe Database contiene metodi che non sono forniti come istruzioni DML. Ad esempio, i metodi utilizzati per il controllo e il rollback delle transazioni, per lo svuotamento del Cestino e i metodi relativi alle query SOQL. Studierai il SOQL in un'altra unità.

Esempio: inserimento di record parzialmente riuscito

Vediamo un esempio che utilizza i metodi Database. Questo esempio si basa sull'esempio di DML in blocco, ma sostituisce l'istruzione DML con un metodo Database. Il metodo Database.insert() viene chiamato con l'opzione di riuscita parziale. Uno dei referenti nell'elenco viene inizializzato di proposito senza alcun campo e causerà un errore perché il referente non può essere salvato senza il campo obbligatorio LastName. Tre referenti vengono inseriti e il referente senza alcun campo genera un errore. L'ultima parte di questo esempio esegue un'iterazione sui risultati restituiti e scrive messaggi di debug nel registro di debug.

  1. Esegui questo esempio nella finestra Execute Anonymous (Esecuzione anonima) della Developer Console.
    // Create a list of contacts
    List<Contact> conList = new List<Contact> {
            new Contact(FirstName='Joe',LastName='Smith',Department='Finance'),
            new Contact(FirstName='Kathy',LastName='Smith',Department='Technology'),
            new Contact(FirstName='Caroline',LastName='Roth',Department='Finance'),
            new Contact()};
    // Bulk insert all contacts with one DML call
    Database.SaveResult[] srList = Database.insert(conList, false);
    // Iterate through each returned result
    for (Database.SaveResult sr : srList) {
        if (sr.isSuccess()) {
            // Operation was successful, so get the ID of the record that was processed
            System.debug('Successfully inserted contact. Contact ID: ' + sr.getId());
        } else {
            // Operation failed, so get all errors
            for(Database.Error err : sr.getErrors()) {
                System.debug('The following error has occurred.');
                System.debug(err.getStatusCode() + ': ' + err.getMessage());
                System.debug('Contact fields that affected this error: ' + err.getFields());
    	 }
        }
    }
  2. Verifica i messaggi di debug (usa la parola chiave DEBUG per il filtro).
    Dovrebbe essere segnalato un solo errore e dovrebbero essere stati inseriti tre referenti.

È meglio usare le istruzioni DML o i metodi Database?

  • Usa le istruzioni DML se desideri che gli eventuali errori che si verificano durante l'elaborazione DML in blocco risultino nella generazione di eccezioni Apex che interrompono immediatamente il flusso di controllo (tramite l'utilizzo di blocchi try...catch). Questo comportamento è simile al modo in cui le eccezioni vengono gestite nella maggior parte dei linguaggi procedurali per database.
  • Utilizza i metodi della classe Database se desideri consentire una riuscita parziale di un'operazione DML in blocco: se per un record si verifica un errore, il resto dell'operazione DML può comunque concludersi correttamente. L'applicazione può quindi ispezionare i record rifiutati ed eventualmente riprovare l'operazione. Utilizzando questo formato, puoi scrivere un codice che non genera mai errori di eccezione DML. Al contrario, il tuo codice può utilizzare l'array di risultati appropriato per valutare se l'operazione è stata completata correttamente o se si sono verificati errori. Nota che i metodi Database includono anche una sintassi che supporta le eccezioni generate, in modo simile alle istruzioni DML.

È possibile creare e gestire record collegati tra loro attraverso le relazioni.

Inserire record correlati

Puoi inserire record correlati a record esistenti se è già stata definita una relazione tra i due oggetti, ad esempio una relazione di ricerca o record principale-record dettaglio. Un record è associato a un record correlato attraverso un ID di chiave esterna. Ad esempio, se si inserisce un nuovo referente, è possibile specificare il record account correlato al referente impostando il valore del campo AccountId.

Questo esempio mostra come aggiungere un referente a un account (il record correlato) impostando il campo AccountId sul referente. Referente e Account sono collegati attraverso una relazione di ricerca.

  1. Esegui questo snippet nella finestra utilizzando l'esecuzione Apex anonima della Developer Console.
    Account acct = new Account(Name='SFDC Account');
    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 mario = new Contact(
        FirstName='Mario',
        LastName='Ruiz',
        Phone='415.555.1212',
        AccountId=acctID);
    insert mario;
  2. Ispeziona i referenti dell'organizzazione.
    È stato creato un nuovo account (SDFC Account) il cui elenco correlato Contacts (Referenti) contiene il referente Mario Ruiz.

Aggiornare record correlati

I campi dei record correlati non possono essere aggiornati con la stessa chiamata all'operazione DML e richiedono una chiamata DML separata. Ad esempio, se si inserisce un nuovo referente, è possibile specificare il record account correlato al referente impostando il valore del campo AccountId. Tuttavia, non è possibile cambiare il nome dell'account senza aggiornare l'account stesso con una chiamata DML separata. Allo stesso modo, quando si aggiorna un referente, se si desidera aggiornare anche l'account correlato al referente, è necessario effettuare due chiamate DML. Nell'esempio seguente un referente e l'account a cui è associato vengono aggiornati utilizzando due istruzioni update.

// Query for the contact, which has been associated with an account.
Contact queriedContact = [SELECT Account.Name
                          FROM Contact
                          WHERE FirstName = 'Mario' AND LastName='Ruiz'
                          LIMIT 1];
// Update the contact's phone number
queriedContact.Phone = '(415)555-1213';
// Update the related account industry
queriedContact.Account.Industry = 'Technology';
// Make two separate calls
// 1. This call is to update the contact's phone.
update queriedContact;
// 2. This call is to update the related account's Industry field.
update queriedContact.Account;

Eliminare record correlati

L'operazione delete supporta eliminazioni a cascata. Eliminando un oggetto principale, si eliminano automaticamente anche gli oggetti secondari, a patto che ciascun record secondario sia eliminabile.

Ad esempio, eliminando l'account creato in precedenza (SDFC Account), viene eliminato anche il referente ad esso correlato.

  1. Esegui questo snippet nella finestra utilizzando l'esecuzione Apex anonima della Developer Console.
    Account[] queriedAccounts = [SELECT Id FROM Account WHERE Name='SFDC Account'];
    delete queriedAccounts;
  2. Controlla gli account e i referenti della tua organizzazione.
    Vedrai che sia l'account che il referente correlato sono stati eliminati.

Informazioni sulle transazioni

Le operazioni DML vengono eseguite all'interno di una transazione. Tutte le operazioni DML di una transazione devono concludersi correttamente oppure, se si verifica un errore in un'operazione, l'intera transazione viene annullata e non viene eseguito il commit di alcun dato nel database. Il confine di una transazione può essere un trigger, il metodo di una classe, un blocco di codice anonimo, una pagina Apex o il metodo di un servizio web personalizzato. Ad esempio, se un trigger o una classe creano due account e aggiornano un referente e l'aggiornamento del referente non riesce per un errore della regola di convalida, l'intera transazione subisce un rollback e nessuno degli account viene salvato in modo permanente in Salesforce.

Risorse

Condividi il tuo feedback su Trailhead dalla Guida di Salesforce.

Conoscere la tua esperienza su Trailhead è importante per noi. Ora puoi accedere al modulo per l'invio di feedback in qualsiasi momento dal sito della Guida di Salesforce.

Scopri di più Continua a condividere il tuo feedback