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 Statements | Database 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:
- 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.
- 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.
- 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:
- isSuccess(): This method returns
true
if the operation was successful, andfalse
otherwise. - getErrors(): If the operation fails, this method returns a list of errors that occurred.
- 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 traditionalinsert
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!