DML Statements in Apex

When working with Salesforce, one of the most important things you’ll do is interact with data stored in your Salesforce database. Apex provides a powerful way to manage this data using DML (Data Manipulation Language) statements. If you’re a student with little or no programming experience, don’t worry! This article will explain DML in simple terms and help you understand how it works in Salesforce.

What is an SObject in Salesforce Apex?

Before we jump into DML, it’s important to understand what an SObject is. In Salesforce, all data is stored in records that are part of standard or custom objects. For example, Account and Contact are standard objects, while you can create custom objects like Student or Course for your own business needs.

In Apex, these records are treated as SObjects. An SObject is simply a data type that represents an object or record in Salesforce. For example, when you create a new Account record, you’re actually working with an Account SObject.

Example:

Account acc = new Account();
acc.Name = 'ABC Corporation';  // Setting the account's name

Here, acc is an SObject that represents an Account record.

Types of DML Statements in Apex

DML statements are commands that allow you to insert, update, delete, undelete, and merge records in Salesforce. Let’s go through each type:

1. Insert Statement

This statement is used to add new records to Salesforce. If you have a new record you want to save to the database, you’ll use the insert DML statement.

Example:

Account acc = new Account(Name = 'XYZ Corporation');
insert acc;

This will create a new Account record named ‘XYZ Corporation’.

2. Update Statement

The update statement allows you to modify an existing record.

Example:

Account acc = [SELECT Id, Name FROM Account WHERE Name = 'XYZ Corporation'];
acc.Name = 'XYZ Corp Modified';  // Changing the name
update acc;

This updates the name of the Account from ‘XYZ Corporation’ to ‘XYZ Corp Modified’.

3. Delete Statement

The delete statement removes records from Salesforce.

Example:

Account acc = [SELECT Id FROM Account WHERE Name = 'XYZ Corp Modified'];
delete acc;

This deletes the Account record named ‘XYZ Corp Modified’.

4. Undelete Statement

If you delete a record but later realize you need it back, you can use undelete.

Example:

Account acc = [SELECT Id FROM Account WHERE IsDeleted = TRUE LIMIT 1 ALL ROWS];
undelete acc;

This recovers a previously deleted record.

5. Merge Statement

The merge statement combines up to three records of the same type, keeping one as the master record and merging others into it.

Example:

Account masterAcc = [SELECT Id FROM Account WHERE Name = 'Master Account'];
Account mergeAcc = [SELECT Id FROM Account WHERE Name = 'Duplicate Account'];
merge masterAcc mergeAcc;

This merges ‘Duplicate Account’ into ‘Master Account’.

Database Class Methods for DML Operations

Apex also provides another way to perform DML operations using the Database class. The Database class offers more flexibility than DML statements. Let’s explore these methods:

1. Database.insert()

This works like the normal insert statement but allows you to specify whether to allow partial success.

Example:

Account acc = new Account(Name = 'ABC Corp');
Database.SaveResult sr = Database.insert(acc, false); // false means partial success is not allowed

2. Database.update()

Similar to the update DML statement, but provides more control.

Example:

Account acc = [SELECT Id, Name FROM Account WHERE Name = 'XYZ Corporation'];
acc.Name = 'XYZ Corp Updated';
Database.SaveResult sr = Database.update(acc, false);

3. Database.delete()

Like the delete DML, but can be used to control whether partial success is allowed.

Example:

Account acc = [SELECT Id FROM Account WHERE Name = 'XYZ Corp Updated'];
Database.delete(acc, false);

Difference Between DML Statements and Database Class Methods

While both DML statements and Database class methods serve the same purpose, they have some important differences:

DML StatementsDatabase Class Methods
Simpler and easier to use.Provides more control and flexibility.
Throws an exception if there’s an error, stopping further execution.Allows for partial success with allOrNone parameter.
Ideal for simple operations.Better for complex operations or bulk inserts.

Considerations/Limitations of DML Statements

When working with DML, there are a few things to keep in mind:

  1. Governor Limits: Salesforce enforces limits on the number of DML operations that can be performed in a single transaction. For example, you can only perform 150 DML statements in a single transaction.
  2. All or None Behavior: DML statements by default follow an “all-or-none” behavior. If one record fails, the entire transaction is rolled back. This can be controlled with Database class methods.
  3. Bulk DML: DML statements are optimized for handling multiple records at once, but there are limitations to how many records you can insert or update in a single transaction.

Example of Bulk DML:

List<Account> accList = new List<Account>();
accList.add(new Account(Name = 'Account 1'));
accList.add(new Account(Name = 'Account 2'));
insert accList;

This inserts multiple Account records in one go.


Understanding Database.SaveResult Class in Apex

In addition to using DML statements, Salesforce provides a flexible and robust way to handle DML operations using the Database class, which can return detailed results of each operation through the Database.SaveResult class.

The Database.SaveResult class is especially useful when performing DML operations like insert, update, or delete using methods like Database.insert(), Database.update(), or Database.delete(). It gives you detailed information on whether the operation succeeded or failed, which is critical when handling multiple records and dealing with potential errors.

Why Use Database.SaveResult?

When performing DML operations using traditional statements like insert, update, or delete, an exception is thrown if there’s any issue (like a validation rule failure or required field missing). This stops further execution, and it becomes difficult to handle partial success.

The Database.SaveResult class, used with methods like Database.insert(), helps you capture success or failure for each record, providing much more control, especially when dealing with bulk operations.

Key Properties of Database.SaveResult

The Database.SaveResult class has several important properties that help you understand the outcome of DML operations:

  1. isSuccess(): This method returns true if the operation was successful, and false otherwise.
  2. getErrors(): If the operation fails, this method returns a list of errors that occurred.
  3. getId(): If the operation is successful, this method returns the ID of the record that was inserted or updated.

Example of Using Database.SaveResult

Here’s how you can use the Database.SaveResult class to capture the result of an insert operation and handle both successes and errors:

List<Account> accList = new List<Account>();
accList.add(new Account(Name = 'Account 1')); // Valid record
accList.add(new Account()); // Invalid record (Name is required)

// Performing a bulk insert
List<Database.SaveResult> results = Database.insert(accList, false); // allOrNone set to false

// Processing results
for (Database.SaveResult sr : results) {
    if (sr.isSuccess()) {
        // If the operation was successful, log the record ID
        System.debug('Successfully inserted record with ID: ' + sr.getId());
    } else {
        // If there was an error, display the error messages
        for (Database.Error err : sr.getErrors()) {
            System.debug('Error: ' + err.getMessage());
        }
    }
}

Breakdown of the Code:

  • Database.insert(accList, false): We use the Database.insert() method instead of the traditional insert statement. The second parameter (false) indicates that partial success is allowed, meaning that if one record fails, the rest can still be processed.
  • isSuccess(): For each result, we check whether the operation succeeded.
  • getErrors(): If the operation failed, we loop through the error messages to find out what went wrong.

Use Case of Database.SaveResult

The Database.SaveResult class is particularly helpful when you are performing operations on multiple records at once. Consider a situation where you want to insert 100 records, but 5 of them fail because of missing fields or validation errors. If you were using regular DML statements, the entire operation would fail, and none of the records would be saved.

Using the Database.SaveResult class with the allOrNone flag set to false, you can capture which records were successfully processed and which ones failed, and handle the errors for the failed ones without affecting the successful records.

Example with Update Operation

Here’s another example using the Database.SaveResult class for an update operation:

List<Account> accList = [SELECT Id, Name FROM Account LIMIT 10];
for (Account acc : accList) {
    acc.Name += ' - Updated'; // Appending " - Updated" to each name
}

// Performing a bulk update
List<Database.SaveResult> updateResults = Database.update(accList, false);

// Processing the results
for (Database.SaveResult sr : updateResults) {
    if (sr.isSuccess()) {
        System.debug('Successfully updated record with ID: ' + sr.getId());
    } else {
        for (Database.Error err : sr.getErrors()) {
            System.debug('Error: ' + err.getMessage());
        }
    }
}

Handling Errors with Database.SaveResult

Errors captured in the Database.SaveResult object can be related to many things, such as:

  • Validation Rule Failures: The record doesn’t meet the criteria set by a validation rule.
  • Required Field Missing: A required field isn’t populated.
  • Field Data Type Issues: Incompatible data types are assigned to fields.

By understanding DML statements in Apex, you’re taking a major step toward becoming proficient in Salesforce development. These commands allow you to manipulate data in Salesforce, and mastering them is crucial for building robust applications.

The Database.SaveResult class gives you precise control over DML operations in Apex. By using it, you can capture the success or failure of each individual record, handle errors gracefully, and even allow partial successes when working with multiple records. It’s an invaluable tool when you’re performing bulk operations, and understanding how to use it will make your code much more reliable and flexible.

With this knowledge, you can now confidently handle data manipulation in Salesforce Apex, ensuring that your code is robust and able to manage errors and successes alike gracefully!

Now that you’ve learned about DML statements, practice using them in your Salesforce org to get comfortable. Happy coding!