Skip to content
Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
DictionaryDData Manipulation Language (DML)
DevelopmentIntermediate

Data Manipulation Language (DML)

Data Manipulation Language (DML) in Salesforce is the set of Apex statements and operations that create, modify, remove, or restore records in the Salesforce database.

§ 01

Definition

Data Manipulation Language (DML) in Salesforce is the set of Apex statements and operations that create, modify, remove, or restore records in the Salesforce database. The statements are insert, update, upsert, merge, delete, and undelete. You write them either as bare statements on a single sObject or a list of sObjects (for example, insert acctList), or as Database class methods such as Database.insert and Database.update that return Result objects with per-record success and error detail. The short version: SOQL reads data, DML writes it.

DML in Apex resembles DML in a traditional SQL database, but it carries Salesforce-specific rules. Every operation runs inside an Apex transaction and counts against governor limits, the headline being 150 DML statements per transaction. Each write also kicks off downstream automation: validation rules, triggers, flows, and any other configured logic all run as part of the same save. Writing DML well means staying inside those limits and handling the side effects on purpose, not by accident.

§ 02

How DML moves data through a Salesforce transaction

The six DML operations and what each one does

Six operations cover every way Apex changes data. insert creates new records and populates their Id field on success. update modifies existing records that already have an Id. delete sends records to the Recycle Bin rather than erasing them immediately. undelete restores records from the Recycle Bin, which holds deleted data for 15 days before hard deletion. merge consolidates up to three records of the same object type into one master, deletes the losers, and re-parents their child records; only leads, contacts, cases, and accounts support merge. upsert is the combination operation: for each record it checks whether a match already exists and then either updates it or inserts it. Each operation accepts a single sObject or a list, and the list form is the one you almost always want for performance. A worked insert looks like this: Account a = new Account(Name='Acme'); insert a; After that line runs, a.Id holds the new record Id, ready to use as a foreign key on a child Contact you insert next.

Bare DML statements versus Database class methods

Apex gives you two syntaxes for the same operations. A bare statement (insert myList) is all-or-none by default. If even one record in the list fails, the whole operation throws a DmlException and every record rolls back, including ones that would have saved. That behavior is safe and simple, and it is the right pick when partial saves would leave your data inconsistent. The Database class methods (Database.insert, Database.update, and so on) take an optional second argument. Pass false for allOrNone and the method allows partial success: valid records save, invalid ones do not, and no exception is thrown. Instead you get back an array of Result objects, one per input record, each carrying isSuccess, the new Id, and a list of errors. You loop the results to log or retry the failures. Use bare statements when an all-or-nothing save matches the business rule. Use Database methods with allOrNone=false for bulk jobs where some bad rows are expected and you want the good ones to land anyway.

Governor limits: 150 statements and 10,000 records

Because Apex runs in a shared, multitenant environment, Salesforce caps how much each transaction can do. Two DML limits matter most. You get 150 DML statements per transaction, counting every insert, update, delete, and the rest across all your code and any automation it fires. You also get 10,000 records processed by DML across the whole transaction. Cross either ceiling and the transaction aborts with a LimitException, undoing everything. The classic way to blow the statement limit is putting DML inside a loop. A loop over 200 records that calls insert once per iteration burns 200 statements and dies well past the cap. The fix is bulkification: collect records into a List inside the loop, then run a single insert on the whole list after the loop ends. One statement, up to 10,000 records. This is why experienced developers treat list-based DML as the default, even for code that starts out handling a single record. Requirements grow, and bulk-safe code does not need rewriting when they do.

The save order: what fires when you commit

A single DML write is not one action; it is a sequence Salesforce runs in a fixed order. Knowing that order explains a lot of confusing behavior. The record loads with new field values, then system validation and most validation rules run. If a validation fails, the save stops and the rest never happens. Before triggers run next, operating on the in-memory record so you can change it without a second DML. The record saves to the database but is not yet committed. After triggers fire, then assignment rules, workflow rules, flows, escalation rules, and roll-up summary recalculations, roughly in that band. Any of these can perform their own DML, and that DML counts against the same 150-statement and 10,000-record budget for the transaction. This is how a seemingly small insert in one object snowballs into limit errors: a trigger updates a parent, which fires a flow, which updates a third object, which fires another trigger. Mapping the automation chain on a busy object is often the only way to understand why a bulk load fails.

Upsert and external ID matching for imports

Upsert is the operation built for repeatable data loads. You pass it an external ID field, a custom field marked as External ID on the object, and Salesforce uses that field to decide insert versus update per record. If a stored record already has that external ID value, upsert updates it; if none matches, upsert creates a new record. The syntax is upsert acctList MyExtId__c; If you omit the field, upsert matches on the standard Id instead. This fits a nightly feed from an ERP or billing system where the source already has its own primary keys and you do not want duplicates accumulating night after night. One upsert call replaces the slower pattern of querying first, splitting records into new and existing buckets, then inserting and updating separately. Upsert also has a sharp edge worth knowing: if a single upsert call contains two records carrying the same external ID value, Salesforce cannot tell which one wins and throws a duplicate external ID error. De-duplicate your batch on the external ID before you upsert it.

Mixed DML: why setup and data objects do not mix

Salesforce blocks one specific combination in a single transaction, and the error surprises almost everyone the first time. You cannot perform DML on a setup object and a non-setup object in the same transaction. Setup objects govern access and permissions: User, UserRole, Group, GroupMember, and similar. Non-setup objects are your everyday data: Account, Contact, Opportunity, and custom objects. Insert or update a User in the same transaction as an Account and Apex throws a MixedDmlOperation exception. The restriction exists so that permission changes and data changes do not interleave in ways that grant access incorrectly. The standard fix is to push one of the two operations into a separate transaction. An @future method runs asynchronously in its own transaction, so you do the data DML inline and call a @future method to do the user DML, or the reverse. System.runAs in test code is the common way to set this up cleanly for unit tests. When a method must touch both kinds of object, a short comment explaining the @future split saves the next developer a long, confusing debugging session.

§

Trust & references

Official documentation

Straight from the source - Salesforce's reference material on Data Manipulation Language (DML).

Was this entry helpful?
Help us write better definitions. Quick reactions or detailed edit suggestions.

About the Author

Dipojjal Chakrabarti is a B2C Solution Architect with 29 Salesforce certifications and over 13 years in the Salesforce ecosystem. He runs salesforcedictionary.com to help admins, developers, architects, and cert/interview candidates sharpen their fundamentals. More about Dipojjal.

§

Test your knowledge

Q1. What does DML stand for in Salesforce Apex?

Q2. What is the governor limit on DML statements per Apex transaction?

Q3. How do bare DML statements differ from Database class methods in handling failures?

§

Discussion

Loading…

Loading discussion…