Bearbeiten von Datensätzen mit DML

Lernziele

Nachdem Sie diese Lektion abgeschlossen haben, sind Sie in der Lage, die folgenden Aufgaben auszuführen:
  • Einfügen, Aktualisieren und Löschen von Datensätzen mithilfe von DML
  • Ausführen von DML-Anweisungen als Massenvorgang
  • Einfügen oder Aktualisieren eines Datensatzes mithilfe von "upsert"
  • Abfangen einer DML-Ausnahme
  • Einfügen neuer Datensätze mit der Option für Teilerfolg und Verarbeiten der Ergebnisse mithilfe einer "Database"-Methode
  • Wissen, wann DML-Anweisungen und wann "Database"-Methoden zu verwenden sind
  • Durchführen von DML-Vorgängen in verknüpften Datensätzen

Bearbeiten von Datensätzen mit DML

Erstellen und bearbeiten Sie Datensätze in Salesforce mithilfe der Datenmanipulationssprache (Data Manipulation Language, DML). DML stellt einfache Anweisungen zum Einfügen, Aktualisieren, Zusammenführen, Löschen und Wiederherstellen von Datensätzen bereit und bietet damit eine unkomplizierte Möglichkeit zur Verwaltung von Datensätzen.

Da Apex eine datenorientierte Sprache ist und auf der Lightning Platform gespeichert wird, hat es direkten Zugriff auf Ihre Daten in Salesforce. Im Gegensatz zu anderen Programmiersprachen, die zusätzliche Einrichtung erfordern, um sich mit Datenquellen zu verbinden, ist die Verwaltung von Datensätzen mit Apex DML ein Kinderspiel. Durch Aufrufen von DML-Anweisungen können Sie im Handumdrehen Vorgänge in Ihren Salesforce-Datensätzen ausführen.

In diesem Beispiel wird der Account "Acme" in Salesforce hinzugefügt. Zuerst wird sObject für den Account erstellt und dann als Argument an die insert-Anweisung übergeben, die den Datensatz in Salesforce persistent ablegt.
// Create the account sObject 
Account acct = new Account(Name='Acme', Phone='(415)555-1212', NumberOfEmployees=100);
// Insert the account by using DML
insert acct;

DML-Anweisungen

Die folgenden DML-Anweisungen stehen zur Verfügung.

  • insert (Einfügen)
  • update (Aktualisieren)
  • upsert (Aktualisieren und einfügen)
  • delete (Löschen)
  • undelete (Löschen rückgängig)
  • merge (Zusammenführen)

Jede DML-Anweisung akzeptiert entweder ein einzelnes sObject oder eine Liste (bzw. ein Array) von sObjects. Mithilfe einer Liste von sObjects lassen sich Datensätze wesentlich effizienter verarbeiten.

Mit Ausnahme von zwei Anweisungen handelt es sich bei allen diesen Anweisungen um vertraute Datenbankvorgänge. Die Anweisungen "upsert" und "merge" sind Salesforce-eigene Anweisungen und können sehr praktisch sein.

Mit dem DML-Vorgang "upsert" werden in einer einzigen Anweisung neue Datensätze erstellt und sObject-Datensätze aktualisiert. Dabei wird anhand eines angegebenen Felds oder, wenn kein Feld angegeben wird, anhand des ID-Felds ermittelt, ob es bereits vorhandene Objekte gibt.

Die Anweisung "merge" führt bis zu drei Datensätze desselben sObject-Typs in einem der Datensätze zusammen. Dabei werden die anderen Datensätze gelöscht und alle verknüpften Datensätze neu zugeordnet.

ID-Feld wird automatisch neuen Datensätzen zugewiesen

Beim Einfügen von Datensätzen weist das System jedem Datensatz eine ID zu. Der ID-Wert wird zu einen persistent in der Datenbank abgelegt und zum anderen automatisch in der sObject-Variablen eingetragen, die Sie im DML-Aufruf als Argument verwendet haben.

Das folgende Beispiel zeigt, wie die ID für das sObject abgerufen wird, das dem eingefügten Account entspricht.

// 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

Über die Grundlagen hinaus

Da die sObject-Variable in dem Beispiel die ID nach dem DML-Aufruf enthält, können Sie diese sObject-Variable zur Ausführung weiterer DML-Vorgänge, wie etwa Aktualisierungen, wiederverwenden, da das System in der Lage ist, die sObject-Variable durch Abgleich der ID dem entsprechenden Datensatz zuzuordnen.

Sie können einen Datensatz samt seiner Felder aus der Datenbank abrufen, einschließlich des ID-Felds. Dies ist jedoch nicht mit DML möglich. Sie müssen eine Abfrage mit SOQL schreiben. SOQL wird in einem anderen Abschnitt behandelt.

DML-Massenvorgänge

Sie können DML-Vorgänge entweder für ein einzelnes sObject oder als Massenvorgang für eine Liste von sObjects ausführen. Es wird empfohlen, DML-Massenvorgänge auszuführen, da dadurch das Überschreiten zulässiger Obergrenzen vermieden wird, z. B. die DML-Obergrenze von 150 Anweisungen pro Apex-Transaktion. Diese Obergrenze wurde etabliert, um fairen Zugriff auf gemeinsam genutzte Ressourcen auf der Lightning Platform sicherzustellen. Die Ausführung eines DML-Vorgangs für eine Liste von sObjects wird als eine DML-Anweisung gezählt und nicht als eine Anweisung für jedes sObject.

Im folgenden Beispiel werden Kontakte als Massenvorgang eingefügt, indem in einem Aufruf eine Liste von Kontakten eingefügt wird. Anschließend werden diese Kontakte ebenfalls als Massenvorgang aktualisiert.

  1. Führen Sie diesen Codeauszug mit anonymem Apex-Code in der Entwicklerkonsole aus.
    // 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. Überprüfen Sie die eben erstellten Kontakte in Ihrer Organisation.

    Bei zwei Kontakten aus der Finanzabteilung sollte die Stellenbezeichnung mit Financial analyst ausgefüllt worden sein.

Gleichzeitiges Aktualisieren/Einfügen von Datensätzen

Wenn Sie über eine Liste mit sowohl neuen als auch bereits vorhandenen Datensätzen verfügen, können Sie Einfügungen und Aktualisierungen an allen Datensätzen in der Liste mithilfe der Anweisung "upsert" verarbeiten. Mit "upsert" wird die Erstellung doppelter Datensätze vermieden und Sie können Zeit sparen, da Sie nicht ermitteln müssen, welche Datensätze zuerst vorhanden waren.

Die Anweisung "upsert" gleicht die sObjects mit vorhandenen Datensätzen ab, indem sie die Werte eines Felds vergleicht. Wenn Sie beim Aufrufen dieser Anweisung kein Feld angeben, verwendet die Anweisung "upsert" für den Abgleich des sObject mit vorhandenen Datensätzen in Salesforce die ID des sObject. Alternativ können Sie ein Feld für den Abgleich angeben. Geben Sie für benutzerdefinierte Objekte ein benutzerdefiniertes Feld an, das als externe ID gekennzeichnet ist. Für Standardobjekte können Sie jedes Feld angeben, bei dem die Eigenschaft idLookup auf "true" (wahr) festgelegt ist. Beim E-Mail-Feld eines Kontakts oder Benutzers beispielsweise ist die Eigenschaft idLookup festgelegt. Informationen zum Überprüfen der Eigenschaft eines Felds finden Sie im Handbuch Object Reference for Salesforce and Lightning Platform.

Syntax für "upsert"

upsert sObject | sObject[]

upsert sObject | sObject[]​​ field

Bei dem optionalen Feld handelt es sich um ein Feld-Token. Zur Angabe des Felds "MyExternalID" lautet die Anweisung beispielsweise:
upsert sObjectList Account.Fields.MyExternalId;

"upsert" verwendet den Primärschlüssel (die ID) des sObject-Datensatzes, ein "idLookup"-Feld oder ein Feld für eine externe ID, um zu ermitteln, ob ein neuer Datensatz erstellt oder ein vorhandener aktualisiert werden soll:

  • Wird für den Schlüssel keine Übereinstimmung gefunden, wird ein neuer Objektdatensatz erstellt.
  • Wird für den Schlüssel eine Übereinstimmung gefunden, wird der vorhandene Objektdatensatz aktualisiert.
  • Werden für den Schlüssel mehrere Übereinstimmungen gefunden, wird ein Fehler ausgegeben und der Objektdatensatz wird weder eingefügt noch aktualisiert.

Dieses Beispiel zeigt, wie mit "upsert" in einem Aufruf ein vorhandener Kontaktdatensatz aktualisiert und ein neuer Kontakt eingefügt wird. Dieser upsert-Aufruf aktualisiert den vorhandenen Kontakt "John" und fügt einen neuen Kontakt, "Kathy", ein.

Hinweis

Hinweis

Der upsert-Aufruf gleicht den ersten Kontakt anhand der ID ab. Die Variable "josh" wird für den upsert-Aufruf wiederverwendet. Diese Variable wurde bereits mit der Datensatz-ID aus dem vorherigen insert-Aufruf ausgefüllt, die ID muss daher in diesem Beispiel nicht explizit festgelegt werden.

  1. Führen Sie diesen Codeauszug im Fenster für die anonyme Ausführung der Entwicklerkonsole aus.
    // 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. Überprüfen Sie alle Kontakte in Ihrer Organisation.

    Ihre Organisation verfügt über nur einen "Josh Kaplan"-Datensatz, nicht zwei, da der "upsert"-Vorgang den vorhandenen Datensatz gefunden und ihn aktualisiert hat, statt einen neuen Kontaktdatensatz zu erstellen. Es gibt auch einen "Kathy Brown"-Kontaktdatensatz.

Alternativ können Sie ein Feld für den Abgleich der Datensätze angeben. Im folgenden Beispiel wird das E-Mail-Feld für den Kontakt verwendet, da bei diesem die Eigenschaft idLookup festgelegt ist. Bei diesem Beispiel wird der Kontakt "Jane Smith" eingefügt sowie ein zweites Kontakt-sObject erstellt und mit derselben E-Mail-Adresse ausgefüllt. Anschließend wird "upsert" aufgerufen, um den Kontakt unter Verwendung des E-Mail-Felds für den Abgleich zu aktualisieren.

Hinweis

Hinweis

Wenn in diesem Beispiel "insert" anstelle von "upsert" verwendet worden wäre, wäre ein doppelter "Jane Smith"-Kontakt eingefügt worden.

  1. Führen Sie diesen Codeauszug im Fenster für die anonyme Ausführung der Entwicklerkonsole aus.
    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. Überprüfen Sie alle Kontakte in Ihrer Organisation.

    In Ihrer Organisation sollte nur der Kontakt "Jane Smith" mit der aktualisierten Beschreibung vorhanden sein.

Löschen von Datensätzen

Sie können persistent abgelegte Datensätze mit der Anweisung "delete" löschen. Gelöschte Datensätze werden nicht dauerhaft aus Lightning Platform gelöscht, sondern 15 Tage im Papierkorb abgelegt, wo sie wiederhergestellt werden können.

Das folgende Beispiel zeigt, wie alle Kontakte mit dem Nachnamen "Smith" gelöscht werden. Wenn Sie das Beispiel für DML-Massenvorgänge ausgeführt haben, sollte Ihre Organisation bereits über zwei Kontakte mit dem Nachnamen "Smith" verfügen. Führen Sie diesen Codeauszug mit anonymem Apex-Code in der Entwicklerkonsole aus und überprüfen Sie dann, dass keine zwei Kontakte mit dem Nachnamen "Smith" mehr vorhanden sind.

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

Hinweis

Dieser Codeauszug enthält eine Abfrage zum Abrufen der Kontakte (eine SOQL-Abfrage). SOQL wird in einem anderen Abschnitt behandelt.

Ausnahmen bei DML-Anweisungen

Wenn ein DML-Vorgang fehlschlägt, wird eine Ausnahme des Typs "DmlException" zurückgegeben. Sie können Ausnahmen in Ihrem Code abfangen, um Fehlerbedingungen zu behandeln.

Das folgende Beispiel erzeugt eine "DmlException", da versucht wird, einen Account ohne das Pflichtfeld "Name" einzufügen. Die Ausnahme wird im Abfangblock abgefangen.

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());
}

"Database"-Methoden

Apex enthält die integrierte Klasse "Database", die Methoden bereitstellt, die DML-Vorgänge ausführen und die Gegenstücke von DML-Anweisungen darstellen.

Diese "Database"-Methoden sind statisch und werden für den Klassennamen aufgerufen.

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

Im Gegensatz zu DML-Anweisungen weisen "Database"-Methoden den optionalen Parameter allOrNone auf, mit dem Sie angeben können, ob der Vorgang teilweise erfolgreich sein soll. Wenn dieser Parameter auf "false" (falsch) festgelegt ist und in einer Teilmenge der Datensätze Fehler auftreten, werden die erfolgreichen Datensätze übernommen und für die fehlgeschlagenen Datensätze werden Fehler zurückgegeben. Zudem werden mit der Option für Teilerfolg keine Ausnahmen ausgelöst.

Die Methode "insert" mit auf "false" festgelegtem allOrNone wird wie folgt aufgerufen.

Database.insert(recordList, false);

Die "Database"-Methoden geben Ergebnisobjekte mit Informationen über Erfolg oder Fehlschlag für jeden Datensatz zurück. Einfüge- und Aktualisierungsvorgänge beispielsweise geben jeweils ein Array von "Database.SaveResult"-Objekten zurück.

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

Hinweis

"upsert" gibt "Database.UpsertResult"-Objekte zurück und 'delete' gibt "Database.DeleteResult"-Objekte zurück.

Der Parameter allOrNone ist standardmäßig auf "true" (wahr) festgelegt, was bedeutet, dass sich die "Database"-Methode wie die ihr entsprechende DML-Anweisung verhält und eine Ausnahme auslöst, wenn ein Fehler auftritt.

Die folgenden beiden Anweisungen entsprechen der Anweisung "insert recordList;".

Database.insert(recordList);

Und:

Database.insert(recordList, true);

Über die Grundlagen hinaus

Neben diesen Methoden enthält die Klasse "Database" Methoden, die nicht als DML-Anweisungen verfügbar sind. Dazu zählen beispielsweise Methoden für Transaktionssteuerung und -Rollback, zum Leeren des Papierkorbs sowie Methoden bezüglich SOQL-Abfragen. SOQL wird in einem anderen Abschnitt behandelt.

Beispiel: Einfügen von Datensätzen mit Teilerfolg

Sehen wir uns ein Beispiel an, in dem "Database"-Methode verwendet werden. Dieses Beispiel beruht auf dem Beispiel für DML-Massenvorgänge, verwendet jedoch anstelle der DML-Anweisung eine "Database"-Methode. Die Methode "Database.insert()" wird mit der Option für Teilerfolg aufgerufen. Ein Kontakt in der Liste verfügt absichtlich über keine Felder und führt zu einem Fehler, da der Kontakt ohne das Pflichtfeld LastName nicht gespeichert werden kann. Drei Kontakte werden übernommen und der Kontakt ohne Felder löst einen Fehler aus. Der letzte Teil dieses Beispiels durchläuft die zurückgegebenen Ergebnisse und schreibt Debug-Meldungen ins Debug-Protokoll.

  1. Führen Sie dieses Beispiel im Fenster für die anonyme Ausführung der Entwicklerkonsole aus.
    // 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. Kontrollieren Sie die Debug-Meldungen (verwenden Sie im Filter das Stichwort DEBUG).

    Ein Fehler sollte gemeldet und drei Kontakte sollten eingefügt worden sein.

Sollten DML-Anweisungen oder "Database"-Methoden verwendet werden?

  • Verwenden Sie DML-Anweisungen, wenn alle Fehler, die während der DML-Massenverarbeitung auftreten, eine Apex-Ausnahme auslösen sollen, die den Steuerfluss sofort unterbricht (mithilfe von try. . .catch-Blöcken). Dieses Verhalten ähnelt der Art und Weise, wie Ausnahmen in den meisten prozeduralen Datenbanksprachen behandelt werden.
  • Verwenden Sie Methoden der Klasse "Database", wenn Sie einen Teilerfolg eines DML-Massenvorgangs zulassen möchten – wenn bei einem Datensatz ein Fehlschlag auftritt, kann der Rest des DML-Vorgangs dennoch erfolgreich sein. Ihre Anwendung kann dann die zurückgewiesenen Datensätze prüfen und den Vorgang möglicherweise erneut versuchen. Bei Verwendung dieser Form können Sie Code schreiben, der nie DML-Ausnahmefehler auslöst. Stattdessen kann Ihr Code das geeignete Ergebnis-Array zur Unterscheidung zwischen Erfolg und Fehlschlag verwenden. Beachten Sie, dass "Database"-Methoden auch eine Syntax enthalten, die ausgelöste Ausnahmen unterstützt, ähnlich wie DML-Anweisungen.

Ressourcen

Lernen Sie weiter kostenlos!
Registrieren Sie sich für einen Account, um fortzufahren.
Was ist für Sie drin?
  • Holen Sie sich personalisierte Empfehlungen für Ihre Karriereplanung
  • Erproben Sie Ihre Fähigkeiten mithilfe praktischer Aufgaben und Quizze
  • Verfolgen Sie Ihre Fortschritte nach und teilen Sie sie mit Arbeitgebern
  • Nutzen Sie Mentoren und Karrierechancen