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? In questo badge, la convalida delle sfide pratiche di Trailhead funziona in inglese. Le traduzioni sono fornite tra parentesi come riferimento. Nel tuo Trailhead Playground, accertati di (1) selezionare Stati Uniti per le impostazioni internazionali, (2) impostare la lingua su Inglese e (3) copiare e incollare soltanto i valori in lingua inglese. Segui le istruzioni qui.

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.

    Due referenti del reparto finanziario devono essere compilati con il titolo 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 con la proprietà idLookup impostata su "true". Ad esempio, il campo Email dell'oggetto Contact o User ha la proprietà idLookup 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 Josh Kaplan, non due, perché l'operazione upsert ha trovato il record esistente e lo ha aggiornato anziché creare un nuovo record 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 perché ha la 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 con la descrizione 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 opzionale 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, non vengono generate eccezioni con l'opzione di riuscita parziale.

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 Database si comporta come la relativa controparte in 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. Un solo referente 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.
Continua a imparare gratuitamente!
Registra un account per continuare.
Cosa troverai?
  • Ottieni consigli personalizzati per i tuoi obiettivi di carriera
  • Metti in pratica le tue competenze con sfide pratiche e quiz
  • Monitora e condividi i tuoi progressi con i datori di lavoro
  • Accedi a risorse di tutoraggio e opportunità di carriera