DML stands for Data Manipulation Language. In Apex, DML is how your code creates, modifies, or removes records in the Salesforce database. There are six DML operations, and every Apex transaction that changes data uses at least one of them.
The six DML operations
| Operation | What it does | Common use |
|---|---|---|
insert | Creates new records | New leads from a web form, batch-created cases |
update | Modifies existing records (Id required) | Trigger-driven field updates, async refresh jobs |
upsert | Insert if no match, update if matched | Integrations using external Id as the key |
delete | Soft-deletes (moves to Recycle Bin) | Cleanup jobs, “remove” buttons |
undelete | Restores from Recycle Bin | Recovery flows |
merge | Combines up to 3 records of the same type into one | Lead/Contact/Account dedup workflows |
Syntax: two equivalent forms
Every DML operation has two interchangeable syntaxes — the DML statement and the Database class method.
// DML statement — throws on first failure, all-or-nothing
Account a = new Account(Name = 'Acme');
insert a;
// Database class method — returns SaveResult[] with partial-success option
Database.SaveResult[] results = Database.insert(
new List<Account>{ new Account(Name = 'Acme'), new Account(Name = 'Beta') },
false // allOrNone = false → partial success allowed
);
The choice between the two matters in production — see DML statements vs Database class methods.
Upsert needs an external key
upsert is the one to know cold for integration interviews:
Lead l = new Lead(
Email = 'jane@example.com',
LastName = 'Doe',
Company = 'Acme',
External_Id__c = 'EXT-12345'
);
upsert l External_Id__c; // match on External_Id__c, update or insert accordingly
Without an external Id field, upsert falls back to matching on the standard Id field — which is rarely what an integration actually wants.
Bulkification: always pass collections
Every DML operation accepts a single sObject or a List of sObjects. Always pass the list — even if the list has one record today, it might have 200 tomorrow.
// Bad — one DML statement per record. Will hit the 150-DML limit at 151 records.
for (Case c : cases) {
update c;
}
// Good — one DML statement for the whole batch
update cases;
Apex’s governor limits cap synchronous transactions at 150 DML statements total. A single bulk update of 10,000 records counts as one statement; a loop doing 151 single-record updates fails.
What gets committed when
DML operations within a single Apex transaction are wrapped in an implicit savepoint. If an unhandled exception escapes the entry-point method, every DML in the transaction rolls back. You can also create explicit savepoints with Database.setSavepoint() and roll back manually with Database.rollback().
Trigger interaction
Every DML on an object with triggers fires those triggers — before and after events, recursive calls included. This is why insert on an account inside an account trigger needs guard logic; otherwise you get infinite recursion. (Most production orgs use a trigger framework with a recursion guard for exactly this reason.)
What interviewers are really looking for
Naming the six operations gets you a tick. The real signal is knowing when each one is appropriate, recognising that DML statements and Database methods differ in failure handling, and understanding that bulkification is non-negotiable. Mention partial-success via Database.insert(records, false) and you’re already ahead of most candidates.
Verified against: Apex Developer Guide — Apex DML Operations. Last reviewed 2026-05-17 for Spring ‘26 release.