Apex DML (Data Manipulation Language) operations are essential for inserting, updating, deleting, and restoring data in Salesforce databases. This comprehensive Apex tutorial covers all six DML operations with production-ready code examples and best practices for Salesforce developers.
What are Apex DML Operations?
DML operations in Apex allow developers to manipulate Salesforce records programmatically. Unlike SOQL queries that retrieve data, DML statements modify database records. Apex supports six core DML operations:
- insert – Creates new records
- update – Modifies existing records
- upsert – Creates or updates records based on external ID
- delete – Removes records (moves to Recycle Bin)
- undelete – Restores records from Recycle Bin
- merge – Combines duplicate records
Apex Insert Operation
The insert keyword creates one or more new records in the database. Use insert when you need to add new data to your Salesforce org.
Insert Syntax
// Single record insert sObject; // Multiple records insert sObject[];
Insert Example
// Create and insert a single Lead record Lead l = new Lead(Company='ABC Corp', LastName='Johnson'); insert l; // Bulk insert example Listaccounts = new List (); for(Integer i = 0; i < 200; i++) { accounts.add(new Account(Name = 'Account ' + i)); } insert accounts; // Governor Limits: 150 DML statements per transaction // Best Practice: Always bulkify DML operations
Database.insert() Method
For more control over error handling, use the Database.insert() method:
// Database method with partial success option Listaccounts = new List { new Account(Name = 'Valid Account'), new Account() // Invalid - missing required Name field }; Database.SaveResult[] results = Database.insert(accounts, false); // Process results for(Database.SaveResult sr : results) { if(!sr.isSuccess()) { for(Database.Error err : sr.getErrors()) { System.debug('Error: ' + err.getMessage()); } } }
Apex Update Operation
The update keyword modifies existing records. Always query for the record first, then modify field values before updating.
Update Example
// Create account first
Account a = new Account(Name='MyAcc1');
insert a;
// Query and update the account
Account myAcct = [SELECT Id, Name, BillingCity FROM Account WHERE Name = 'MyAcc1' LIMIT 1];
myAcct.BillingCity = 'Melbourne';
try {
update myAcct;
} catch (DmlException e) {
System.debug('Update failed: ' + e.getMessage());
}
Bulk Update Pattern
// Bulk update example - proper governor limit handling ListaccountsToUpdate = [SELECT Id, Industry FROM Account WHERE Industry = null LIMIT 200]; for(Account acc : accountsToUpdate) { acc.Industry = 'Technology'; } if(!accountsToUpdate.isEmpty()) { update accountsToUpdate; }
Apex Upsert Operation
The upsert operation creates new records or updates existing ones based on an external ID field. This is particularly useful for data integration scenarios.
Upsert Example
// Update existing records and insert new one ListacctsList = [SELECT Id, Name, BillingCity FROM Account WHERE BillingCity = 'Bombay']; for (Account a : acctsList){ a.BillingCity = 'Mumbai'; } // Add new account to the list Account newAcct = new Account(Name = 'Ramco', BillingCity = 'Hyderabad'); acctsList.add(newAcct); try { upsert acctsList; } catch (DmlException e) { System.debug('Upsert failed: ' + e.getMessage()); }
Upsert with External ID
// Upsert using external ID field
Account acc = new Account(
External_ID__c = 'EXT001',
Name = 'External Account',
Industry = 'Manufacturing'
);
// Will update if External_ID__c exists, insert if not
upsert acc External_ID__c;
Apex Delete Operation
The delete DML operation removes one or more existing records from your organization’s data. Deleted records move to the Recycle Bin and can be restored within 15 days.
Delete Syntax
// Single record delete sObject; // Multiple records delete sObject[];
Delete Example
// Query and delete accounts ListdelAccts = [SELECT Id, Name FROM Account WHERE Name = 'Test Account']; try { delete delAccts; System.debug('Deleted ' + delAccts.size() + ' accounts'); } catch (DmlException e) { System.debug('Delete failed: ' + e.getMessage()); }
Important Delete Considerations
- Deleted records remain in Recycle Bin for 15 days
- Related records may prevent deletion due to lookup relationships
- Use ALL ROWS in SOQL to query deleted records
- Consider cascade delete behavior on master-detail relationships
Apex Undelete Operation
The undelete keyword restores records from the Recycle Bin. Use the ALL ROWS clause in SOQL queries to retrieve deleted records.
Undelete Example
// Query deleted records using ALL ROWS ListdeletedAccts = [SELECT Id, Name FROM Account WHERE Name = 'Restored Account' ALL ROWS]; try { undelete deletedAccts; System.debug('Restored ' + deletedAccts.size() + ' accounts'); } catch (DmlException e) { System.debug('Undelete failed: ' + e.getMessage()); }
Apex Merge Operation
The merge operation combines up to three records of the same object type into one master record. The non-master records are deleted, and their related records are reparented to the master.
Merge Example
// Create test accounts ListaccList = new List { new Account(Name='Master Account'), new Account(Name='Duplicate Account') }; insert accList; // Query the accounts for merge Account masterAcct = [SELECT Id, Name FROM Account WHERE Name = 'Master Account' LIMIT 1]; Account duplicateAcct = [SELECT Id, Name FROM Account WHERE Name = 'Duplicate Account' LIMIT 1]; try { merge masterAcct duplicateAcct; System.debug('Accounts merged successfully'); } catch (DmlException e) { System.debug('Merge failed: ' + e.getMessage()); }
Merge Limitations
- Only available for Account, Contact, and Lead objects
- Maximum of 3 records can be merged at once
- Master record retains its ID and field values
- Related records are automatically reparented
DML Best Practices and Governor Limits
Governor Limits
- DML Statements: 150 per transaction (synchronous), 200 (asynchronous)
- Records per DML: 10,000 records per operation
- Total DML Rows: 10,000 per transaction
Best Practices
// ✅ Good: Bulkified DML Listaccounts = new List (); for(Integer i = 0; i < 200; i++) { accounts.add(new Account(Name = 'Bulk Account ' + i)); } insert accounts; // Single DML statement // ❌ Bad: DML in loop for(Integer i = 0; i < 200; i++) { Account acc = new Account(Name = 'Account ' + i); insert acc; // 200 DML statements - will hit governor limit }
Error Handling Patterns
// Use Database methods for partial success scenarios Listaccounts = getAccountsToUpdate(); Database.SaveResult[] results = Database.update(accounts, false); for(Integer i = 0; i < results.size(); i++) { if(!results[i].isSuccess()) { System.debug('Failed to update account: ' + accounts[i].Name); for(Database.Error error : results[i].getErrors()) { System.debug('Error: ' + error.getMessage()); } } }
Frequently Asked Questions
What is the difference between DML statements and Database methods in Apex?
DML statements (insert, update, delete) throw exceptions on any failure and stop processing. Database methods (Database.insert(), Database.update()) allow partial success with the allOrNone parameter set to false, letting you handle individual record failures without stopping the entire operation.
How many DML operations can I perform in a single Apex transaction?
You can perform up to 150 DML statements per synchronous transaction and 200 per asynchronous transaction. Each statement can process up to 10,000 records, with a total limit of 10,000 DML rows per transaction across all operations.
What happens when I delete a record in Salesforce Apex?
Deleted records move to the Recycle Bin where they remain for 15 days before permanent deletion. You can restore deleted records using the undelete operation. Use the ALL ROWS clause in SOQL queries to retrieve deleted records from the Recycle Bin.
When should I use upsert instead of insert or update in Apex?
Use upsert when you’re not sure if a record exists and want to either create it or update it based on an external ID field. This is common in data integration scenarios where you’re synchronizing data from external systems and need to handle both new and existing records efficiently.
What is the final keyword used for in Apex programming?
The final keyword in Apex prevents modification of variables, methods, or classes. For variables, final means the value cannot be changed after initialization. For methods, final prevents overriding in subclasses. For classes, final prevents inheritance.