What is Triggers in Salesforce?
A trigger is an Apex script that executes before or after data manipulation language (DML) events occur. Apex triggers enable you to perform custom actions before or after events to record in Salesforce, such as insertions, updates, or deletions. Just like database systems support triggers, Apex provides trigger support for managing records.
When to use salesforce triggers
We should use triggers to perform tasks that can’t be done by using the point-and-click tools in the Salesforce user interface. For example, if validating a field value or updating a field on a record, use validation rules and workflow rules instead.
What is Trigger Syntax?
123 trigger TriggerName on ObjectName (trigger_events) {
code_block
}
1 2 3 | trigger TriggerName on ObjectName (trigger_events) { code_block } |
Trigger events in salesforce?
A trigger is a set of statement which can be executed on the following events. In above trigger events one or more of below events can be used with comma-separated.
Here is a list of trigger events in salesforce
- before insert
- before update
- before delete
- after insert
- after update
- after delete
- after undelete
What are different type of Triggers?
There are two types of triggers:
- Before triggers are used to perform a task before a record is inserted or updated or deleted. These are used to update or validate record values before they are saved to the database.
- After triggers are used if we want to use the information set by Salesforce system and to make changes in the other records. are used to access field values that are set by the system (such as a record’s Id or LastModifiedDate field), and to affect changes in other records. The records that fire the after trigger are read-only.
There are two types of triggers:
- Before triggers are used to perform a task before a record is inserted or updated or deleted. These are used to update or validate record values before they are saved to the database.
- After triggers are used if we want to use the information set by Salesforce system and to make changes in the other records. are used to access field values that are set by the system (such as a record’s Id or LastModifiedDate field), and to affect changes in other records. The records that fire the after trigger are read-only.
What are the considerations while implementing the Triggers?
Consider the following before implementing the triggers.
- Upsert trigger fires on 4 different events :- before(insert, update), after (insert, update)
- Merge trigger are fired on both events on delete
- Field history is updated after the trigger has successfully finished processing data.
- Any callout should be asynchronous so that trigger does not have to wait for the response.
- A trigger cannot have a static keyword in its code.
- If a trigger completes successfully the changes are committed to the database and if it fails the transaction is rolled back.
Consider the following before implementing the triggers.
- Upsert trigger fires on 4 different events :- before(insert, update), after (insert, update)
- Merge trigger are fired on both events on delete
- Field history is updated after the trigger has successfully finished processing data.
- Any callout should be asynchronous so that trigger does not have to wait for the response.
- A trigger cannot have a static keyword in its code.
- If a trigger completes successfully the changes are committed to the database and if it fails the transaction is rolled back.
What are context variables in triggers?
All triggers define implicit variables that allow developers to access run-time context. These variables are contained in the System.Trigger class.
Here is list of context variables in triggers
- isExecuting: Returns true if the current context for the Apex code is a trigger, not a Visualforce page, a Web service, or an executeanonymous() API call.
- isInsert: Returns true if this trigger was fired due to an insert operation, from the Salesforce user interface, Apex, or the API.
- isUpdate: Returns true if this trigger was fired due to an update operation, from the Salesforce user interface, Apex, or the API.
- isDelete: Returns true if this trigger was fired due to a delete operation, from the Salesforce user interface, Apex, or the API.
- isBefore: Returns true if this trigger was fired before any record was saved.
- isAfter: Returns true if this trigger was fired after all records were saved.
- isUndelete: Returns true if this trigger was fired after a record is recovered from the Recycle Bin (that is, after an undelete operation from the Salesforce user interface, Apex, or the API.)
- new: Returns a list of the new versions of the sObject records. This sObject list is only available in insert, update, and undelete triggers, and the records can only be modified in before triggers.
- newMap: A map of IDs to the new versions of the sObject records. This map is only available in before update, after insert, after update, and after undelete triggers.
- old : Returns a list of the old versions of the sObject records. This sObject list is only available in update and delete triggers.
- oldMap: A map of IDs to the old versions of the sObject records. This map is only available in update and delete triggers.
- size: The total number of records in a trigger invocation, both old and new.
All triggers define implicit variables that allow developers to access run-time context. These variables are contained in the System.Trigger class.
Here is list of context variables in triggers
- isExecuting: Returns true if the current context for the Apex code is a trigger, not a Visualforce page, a Web service, or an executeanonymous() API call.
- isInsert: Returns true if this trigger was fired due to an insert operation, from the Salesforce user interface, Apex, or the API.
- isUpdate: Returns true if this trigger was fired due to an update operation, from the Salesforce user interface, Apex, or the API.
- isDelete: Returns true if this trigger was fired due to a delete operation, from the Salesforce user interface, Apex, or the API.
- isBefore: Returns true if this trigger was fired before any record was saved.
- isAfter: Returns true if this trigger was fired after all records were saved.
- isUndelete: Returns true if this trigger was fired after a record is recovered from the Recycle Bin (that is, after an undelete operation from the Salesforce user interface, Apex, or the API.)
- new: Returns a list of the new versions of the sObject records. This sObject list is only available in insert, update, and undelete triggers, and the records can only be modified in before triggers.
- newMap: A map of IDs to the new versions of the sObject records. This map is only available in before update, after insert, after update, and after undelete triggers.
- old : Returns a list of the old versions of the sObject records. This sObject list is only available in update and delete triggers.
- oldMap: A map of IDs to the old versions of the sObject records. This map is only available in update and delete triggers.
- size: The total number of records in a trigger invocation, both old and new.
Salesforce Trigger Example
before insert trigger salesforce
Account trigger to set account rating as ‘Hot’ if account industry is ‘Banking’ or ‘Healthcare’
Account trigger to set account rating as ‘Hot’ if account industry is ‘Banking’ or ‘Healthcare’
before update trigger salesforce
trigger AccountCustomTrigger on Account (before insert, before update) {
for
(Account acc : Trigger.New) {
if
(acc.Industry !=
null
&& (acc.Industry ==
'Banking'
|| acc.Industry ==
'Healthcare'
)){
acc.Rating =
'Hot'
;
}
}
}
after insert trigger salesforce
Let us see one more example of a trigger on contact which will create Account record whenever contact is created without an account.
trigger IMScity__c on IMSCity__c (after insert) {
List<IMSCity__c> accListToInsert =
new
List<IMSCity__c>();
for
(IMSCity__c con : Trigger.New) {
//check if account is null on contact
if
(con.AccountId ==
null
) {
Account acc =
new
Account();
//Add all required field on Account
acc.Name = con.LastName;
acc.Phone = con.Phone;
accListToInsert.add(acc);
}
}
if
(!accListToInsert.isEmpty()){
insert accListToInsert;
}
}
Define Recursive Trigger and how to avoid it?
There is a possibility that the result of the trigger can end up calling the same trigger again and can run in a loop, this is known as a recursive trigger. To avoid this scenario we should create a static variable and check the value of this variable before we execute anything in the trigger. For more details refer to below link:
trigger SampleTrigger on Contact (after update){
Set<String> accIdSet =
new
Set<String>();
if
(RecursiveTriggerHandler.isFirstTime){
RecursiveTriggerHandler.isFirstTime =
false
;
for
(Contact conObj : Trigger.New){
if
(conObj.name !=
'SFDC'
){
accIdSet.add(conObj.accountId);
}
}
// Use accIdSet in some way
}
}
What do you mean by the bulkifying trigger?
A trigger should be able to handle single record and thousands of record. There are two important point for bulkifying trigger:
- Write triggers that operate on collections of sObjects.
- Write triggers that perform efficient SOQL and DML operations.
If we will not follow above point we may hit governor limit when records are created/updated/deleted in mass using data loader or other tool.
Example 1
trigger SoqlTriggerBulk on Account(after update) {
// Perform SOQL query once.
// Get the related opportunities for the accounts in this trigger.
List<Opportunity> relatedOpps = [SELECT Id,Name,CloseDate FROM Opportunity
WHERE AccountId IN :Trigger.new];
// Iterate over the related opportunities
for(Opportunity opp : relatedOpps) {
// Do some other processing
}
}
Example 2
trigger DmlTriggerBulk on Account(after update) {
// Get the related opportunities for the accounts in this trigger.
List<Opportunity> relatedOpps = [SELECT Id,Name,Probability FROM Opportunity
WHERE AccountId IN :Trigger.new];
List<Opportunity> oppsToUpdate = new List<Opportunity>();
// Iterate over the related opportunities
for(Opportunity opp : relatedOpps) {
// Update the description when probability is greater
// than 50% but less than 100%
if ((opp.Probability >= 50) && (opp.Probability < 100)) {
opp.Description = 'New description for opportunity.';
oppsToUpdate.add(opp);
}
}
// Perform DML on a collection
update oppsToUpdate;
}
What is the meaning of before insert?
The BeforeInsert event occurs when the user types the first character in a new record, but before the record is actually created.
trigger MyCustomObjectTrigger on MyCustomObject__c (before insert) {
// This trigger will run before records of the MyCustomObject__c object are inserted.
// You can access and modify the records that are being inserted in the Trigger.new list.
List<MyCustomObject__c> recordsToInsert = Trigger.new;
for (MyCustomObject__c record : recordsToInsert) {
// Perform your custom logic here, such as data validation or field manipulation.
// For example, you can set a default value for a field.
record.CustomField__c = 'Default Value';
}
}
What is before update trigger ?
Before triggers are used
to update or validate record values before they're saved to the database. After triggers are used to access field values that are set
by the system (such as a record's Id or LastModifiedDate field), and to affect
changes in other records. The records that fire the after trigger are read-only.
trigger
MyCustomObjectTrigger on MyCustomObject__c (before update) {
// This
trigger will run before records of the MyCustomObject__c object are updated.
// You
can access and modify the records that are being updated in the Trigger.new
list.
List<MyCustomObject__c> recordsToUpdate = Trigger.new;
for
(MyCustomObject__c record : recordsToUpdate) {
// Perform your custom logic here, such as data validation or field
manipulation.
// For example, you can update a field based on certain conditions.
if (record.SomeField__c == 'ConditionMet') {
record.AnotherField__c = 'Updated Value';
}
}
}
What is before delete trigger?
BEFORE DELETE Trigger in MySQL is invoked
automatically whenever a delete operation is fired on the table. In this article, we are going to learn how to create a
before delete trigger with its syntax and example.
trigger MyCustomObjectTrigger on MyCustomObject__c (before delete) {
// This trigger will run before records of the MyCustomObject__c object are deleted.
// You can access and work with the records that are being deleted in the Trigger.old list.
List<MyCustomObject__c> recordsToDelete = Trigger.old;
for (MyCustomObject__c record : recordsToDelete) {
// Perform your custom logic here, such as validation or related record cleanup.
// For example, you can check if certain conditions are met before deletion.
if (record.Status__c == 'Approved') {
record.addError('Cannot delete approved records.');
}
}
}
What is after insert trigger?
An AFTER INSERT Trigger means that MySQL
will fire this trigger after the INSERT operation is executed.
trigger MyCustomObjectTrigger on MyCustomObject__c (after insert) {
// This trigger will run after records of the MyCustomObject__c object are inserted.
// You can access the records that have been successfully inserted in the Trigger.new list.
List<MyCustomObject__c> insertedRecords = Trigger.new;
// Perform your custom logic here based on the newly inserted records.
for (MyCustomObject__c record : insertedRecords) {
// Perform actions such as sending notifications, creating related records, or updating other objects.
// For example, you can create a related record for each newly inserted record.
CustomRelatedObject__c relatedRecord = new CustomRelatedObject__c();
relatedRecord.ParentRecordId__c = record.Id;
relatedRecord.Name = 'Related Record';
insert relatedRecord;
}
}
What is after update trigger?
AFTER UPDATE Trigger in SQL is a
stored procedure on a database table that gets invoked or triggered
automatically after an UPDATE operation gets successfully executed on the
specified table. For the uninitiated, the UPDATE statement is used to modify
data in existing rows of a data table.
trigger MyCustomObjectTrigger on MyCustomObject__c (after update) {
// This trigger will run after records of the MyCustomObject__c object are updated.
// You can access the records that have been successfully updated in the Trigger.new list.
List<MyCustomObject__c> updatedRecords = Trigger.new;
// You can also access the previous version of the records using the Trigger.old list.
List<MyCustomObject__c> oldRecords = Trigger.old;
// Perform your custom logic here based on the updated records.
for (Integer i = 0; i < updatedRecords.size(); i++) {
MyCustomObject__c newRecord = updatedRecords[i];
MyCustomObject__c oldRecord = oldRecords[i];
// Compare the new and old values to identify changes and take actions accordingly.
if (newRecord.Status__c != oldRecord.Status__c) {
// Status field has changed; perform additional logic.
// For example, send a notification or log the change.
System.debug('Status has been updated: ' + oldRecord.Status__c + ' -> ' + newRecord.Status__c);
}
}
}
What is after delete trigger?
The AFTER DELETE Trigger in MySQL is invoked
automatically whenever a delete event is fired on the table. In this article, we are going to learn how to create an
AFTER DELETE trigger with its syntax and example.
trigger MyCustomObjectTrigger on MyCustomObject__c (after delete) {
// This trigger will run after records of the MyCustomObject__c object are deleted.
// You can access the records that have been successfully deleted in the Trigger.old list.
List<MyCustomObject__c> deletedRecords = Trigger.old;
// Perform your custom logic here based on the deleted records.
for (MyCustomObject__c record : deletedRecords) {
// Perform actions such as logging the deletion or creating related records.
// For example, you can create an audit log entry for each deleted record.
AuditLog__c auditRecord = new AuditLog__c();
auditRecord.ObjectName__c = 'MyCustomObject__c';
auditRecord.Action__c = 'Deleted';
auditRecord.RecordId__c = record.Id;
insert auditRecord;
}
}
What is after undelete trigger?
The after undelete trigger event only
works with recovered records—that is, records
that were deleted and then recovered from the Recycle Bin through the undelete
DML statement. These are also called undeleted records. Ex: If
you delete an Account, an Opportunity may also be deleted.
trigger MyCustomObjectTrigger on MyCustomObject__c (after undelete) {
// This trigger will run after records of the MyCustomObject__c object are undeleted.
// You can access the records that have been successfully undeleted in the Trigger.new list.
List<MyCustomObject__c> undeletedRecords = Trigger.new;
// Perform your custom logic here based on the undeleted records.
for (MyCustomObject__c record : undeletedRecords) {
// Perform actions such as sending notifications, creating related records, or updating other objects.
// For example, you can update a field or send a notification after undeletion.
record.IsRecovered__c = true;
}
}
What are different type of Triggers?
There are two types of triggers:
Before triggers are used to perform a task before a record is
inserted or updated or deleted. These are used to update or validate
record values before they are saved to the database.
After triggers are used if we want to use the information set by
Salesforce system and to make changes in the other records. are used to
access field values that are set by the system (such as a record’s Id or LastModifiedDate field), and to affect changes in other records. The
records that fire the after trigger are read-only.
What is isExecuting triggers?
isexecuting is used to identify that the current context for the Apex code is a
trigger and the apex code is not getting called from any other sources like
webservice, visualforce page, etc
trigger MyCustomObjectTrigger on MyCustomObject__c (before insert, before update, before delete, before undelete, after insert, after update, after delete, after undelete) {
if (Trigger.isExecuting) {
// The trigger is executing in the "before" context.
if (Trigger.isBefore) {
System.debug('This is a "before" trigger.');
} else {
System.debug('This is an "after" trigger.');
}
} else {
// The trigger is executing in the "after" context.
System.debug('This is an "after" trigger.');
}
}
What is isInsert triggers?
IsInsert " returns true if this
trigger was fired due to an insert operation, from the Salesforce user
interface, Apex, or the API. "Trigger. IsUpdate" returns
true if this trigger was fired due to an update operation, from the Salesforce
user interface, Apex, or the API.
trigger MyCustomObjectTrigger on MyCustomObject__c (before insert) {
// Define a custom variable to check if it's an insert operation.
Boolean isInsert = true;
// Check if it's an insert operation.
if (isInsert) {
// Your logic for the insert operation goes here.
System.debug('This is an insert operation.');
}
}
What is isUpdate triggers?
isUpdate. Returns
true if this trigger was fired due to an update operation, from the Salesforce
user interface, Apex, or the API. isDelete. Returns true if this trigger was fired due to a
delete operation, from the Salesforce user interface, Apex, or the API.
isBefore.
trigger MyCustomObjectTrigger on MyCustomObject__c (before update) {
// Define a custom variable to check if it's an update operation.
Boolean isUpdate = true;
// Check if it's an update operation.
if (isUpdate) {
// Your logic for the update operation goes here.
System.debug('This is an update operation.');
}
}
What is isDelete triggers?
isDelete: It
will check if this trigger was fired due to a delete operation. isBefore: It will check if this trigger was fired before
any record was saved. isAfter: It will check if this trigger was fired after
all records were saved.
trigger MyCustomObjectTrigger on MyCustomObject__c (before delete, after delete) {
if (Trigger.isBefore) {
// This is a "before" trigger, which means it's operating in the delete context.
System.debug('This is a "before delete" trigger.');
} else {
// This is an "after" trigger, which means it's operating in the delete context.
System.debug('This is an "after delete" trigger.');
}
}
What is isBefore triggers?
Returns true if the trigger has been fired before any record was saved
trigger MyCustomObjectTrigger on MyCustomObject__c (before delete, after delete) { if (Trigger.isBefore) { // This is a "before" trigger, which means it's operating in the delete context. System.debug('This is a "before delete" trigger.'); } else { // This is an "after" trigger, which means it's operating in the delete context. System.debug('This is an "after delete" trigger.'); }}
What is isAfter triggers?isAfter. Returns
true if the trigger was fired after all records have been saved. isUndelete. Returns true if the trigger was fired after a
record has been recovered from the Recycle Bin.
trigger MyCustomObjectTrigger on MyCustomObject__c (before insert, before update, before delete, after insert, after update, after delete) {
if (Trigger.isBefore) {
// This is a "before" trigger.
System.debug('This is a "before" trigger.');
} else {
// This is an "after" trigger.
System.debug('This is an "after" trigger.');
}
}
What is isUndelete triggers?
isUndelete. Returns
true if the trigger was fired after a record has been recovered from the
Recycle Bin. new. Returns a list of new versions of the
sObject records.
trigger MyCustomObjectTrigger on MyCustomObject__c (before undelete, after undelete) { if (Trigger.isBefore) { // This is a "before" trigger, which means it's operating in the undelete context. System.debug('This is a "before undelete" trigger.'); } else { // This is an "after" trigger, which means it's operating in the undelete context. System.debug('This is an "after undelete" trigger.'); }}
What is new trigger?
NEW is a
pseudo-record name that refers to the new table row for insert and update
operations in row-level triggers. Its usage is :NEW. column , where column is the name of a
column in the table on which the trigger is defined. When used in a before
row-level trigger , the initial content of :NEW.
trigger MyCustomObjectTrigger on CustomObject__c (before insert, after update) {
if (Trigger.isBefore) {
// Logic to execute before insert.
} else {
// Logic to execute after update.
}
}
What is newMap trigger?
newMap: A map of IDs to the new versions of the sObject records. This map is only available in before update, after insert, after update, and after undelete triggers.
trigger MyMapTrigger on CustomObject__c (before insert) {
// Create a Map to group records by a specific field value.
Map<String, List<CustomObject__c>> recordMap = new Map<String, List<CustomObject__c>>();
for (CustomObject__c record : Trigger.new) {
String fieldValue = record.SomeField__c;
if (!recordMap.containsKey(fieldValue)) {
recordMap.put(fieldValue, new List<CustomObject__c>());
}
recordMap.get(fieldValue).add(record);
}
// Now you can perform actions based on the records grouped in the Map.
for (String key : recordMap.keySet()) {
List<CustomObject__c> records = recordMap.get(key);
// Perform your custom logic here based on the grouped records.
// For example, you can update a related object for each group of records.
}
}
What is old trigger?
This variable returns a list of the old version of sObject
records. This list is only available in update and delete
triggers.
trigger MyOldValuesTrigger on CustomObject__c (before update) {
for (CustomObject__c oldRecord : Trigger.old) {
CustomObject__c newRecord = Trigger.newMap.get(oldRecord.Id);
if (oldRecord.CustomField__c != newRecord.CustomField__c) {
// A change was made to the CustomField__c field.
System.debug('Change detected in CustomField__c: ' + oldRecord.CustomField__c + ' -> ' + newRecord.CustomField__c);
}
}
}
What is oldMap trigger?
A map of IDs to the old versions of the sObject records. This map is only available in update and delete triggers.
trigger MyOldMapTrigger on CustomObject__c (before update) {
Map<Id, CustomObject__c> oldRecords = Trigger.oldMap;
for (Id recordId : oldRecords.keySet()) {
CustomObject__c oldRecord = oldRecords.get(recordId);
CustomObject__c newRecord = Trigger.newMap.get(recordId);
if (oldRecord.CustomField__c != newRecord.CustomField__c) {
// A change was made to the CustomField__c field.
System.debug('Change detected in CustomField__c for record ID ' + recordId + ': ' +
oldRecord.CustomField__c + ' -> ' + newRecord.CustomField__c); } }}
What is size trigger?
Size – The
total number of records in a trigger invocation, both old and new. trigger. size() will return the number of records that
invoked the trigger. few other trigger context variables below. isExecuting –
Returns true if the current context for the Apex code is a trigger.
trigger CountRecordsTrigger on MyCustomObject__c (before insert) {
// Define a variable to count the number of records being inserted.
Integer recordCount = 0;
// Loop through the records being inserted.
for (MyCustomObject__c record : Trigger.new) {
// Increment the record count for each record.
recordCount++;
}
// You can perform logic based on the record count.
if (recordCount > 100) {
// Enforce a limit on the number of records being inserted.
for (MyCustomObject__c record : Trigger.new) {
record.addError('You have exceeded the maximum allowed records for insertion.');
}
}
}