Using database.insert in Salesforce Apex
The database.insert method in Salesforce is the programmatic way to add new records to the database using Apex. Unlike the standard insert statement, the Database.insert method returns a Database.SaveResult object that provides detailed information about the success or failure of each record, which is essential for robust error handling and bulk processing. When you call this method, Salesforce evaluates the record, runs validation rules and triggers, and attempts the DML operation. If the operation fails for any records in a bulk context, the rest continue processing unless you set allOrNone to true. This makes it a powerful tool for data loading, ETL processes, and any scenario where you need to know exactly what happened at the record level rather than getting a single unrecoverable exception.
More from this site
Keep reading the latest coverage
Syntax and Parameters
The core syntax uses the Database.SaveResult array to capture outcomes. The key parameter is allOrNone, a boolean that dictates transaction control. When set to false (the default), each record is processed individually, and failures are isolated. When set to true, the entire operation rolls back if any single record fails. This parameter fundamentally changes the behavior and should be chosen based on whether data integrity or throughput is the priority. The method also accepts a list of SObject records to be inserted, and the returned SaveResult array mirrors the input order, allowing you to correlate the result with the specific input record using the index.
Understanding SaveResult and Error Handling
Each SaveResult object contains an isSuccess boolean and a list of errors. You must iterate over these results to handle partial failures gracefully. When allOrNone is false and a record fails, you can log the error, attempt a fallback, or notify the user without halting the entire transaction. This is particularly important because validation rules and triggers can cause failures that you can diagnose and resolve without discarding the entire batch. The save result provides the error message and status code, giving you programmatic control over the response. For example, you can use a simple for loop to check each result and collect those that failed, then return them in a response or log them for a systems administrator.
Best Practices and Governor Limits
When using this method inside loops or in bulk contexts, you must respect governor limits. The DML statement has limits on the number of records you can process in a single transaction. A common pattern is to chunk a large list of records into smaller lists of 200 and execute the insert method in a loop. This keeps you safely under the limit while maximizing throughput. The database method also provides more detailed error information than a standard insert statement, making it the preferred choice for data integration and API-based bulk loading. Keep in mind the order of results corresponds to the order of input records, so mapping errors back to the original data is straightforward. You should also be aware of mixed DML operations when inserting records with both setup and non-setup objects in the same transaction, as this can lead to unexpected failures.
Examples
Here is a basic example of inserting a single Account record and checking the result:
- Create an Account object with a name.
- Use Database.insert(acc, false) to attempt the operation.
- Check result.isSuccess() to confirm it worked or extract the error message if it did not.
For bulk processing, you would wrap the attempt in a loop processing a list of records in chunks. The size of the chunk is often 200 records. You then call Database.insert(recordChunk, false) for each batch. This approach handles partial failures gracefully and ensures your data loads efficiently. You can also use Database.insertImmediate for scenarios that require an unblockable insert that does not respect the current transaction, though this is rarely used and has specific use cases involving audit trails or platform events.
Conclusion
Using database.insert in Apex provides a reliable way to handle record creation with detailed feedback at the row level. By checking the returned SaveResult objects, you can build resilient integrations and robust batch jobs that handle validation rule errors and trigger failures without crashing the entire transaction. This method is essential for any developer building data import tools or complex automation in Salesforce.