Writing Apex triggers enable you to do custom actions before or after changes to Salesforce records, such as insertions, updates, or deletions. A trigger is an Apex script that executed before or after specific data manipulation language (DML) events occur (such as before object records are added to the database, or after records are deleted). In addition, triggers help you do custom actions before or after changes to Salesforce records.
The trigger is Apex code that executed before or after the following types of operations:
- Insert
- Update
- Delete
- Merge
- Upsert
- Undelete
For example, you can have a trigger run before an object's records in a couple of scenarios. When records are being inserted into the database after records have been deleted, or even after a record is being restored from the Recycle Bin.
There Are Two Types Of Triggers:
- Before triggers: It is used to update or authenticate record values before it is saved in the database.
- After triggers: It is used to access values of the record that are stored in the database and use this value to make changes with other records. After trigger records are read-only.
Trigger trigger Name on sObject(Trigger event) { //logic }
Bulk Triggers
All triggers are bulk triggers by default and can process multiple records at a time. Therefore, I believe you should always plan on processing more than one record at a time. Also, Bulk triggers can handle both single record updates and bulk operations like:
- Data import
- com Bulk API calls
- Mass actions, such as record owner changes and deletes
- Recursive Apex methods and triggers that invoke bulk DML statements
Trigger Context Variables
Apex triggers define implicit variables that allow developers to access run-time context. These variables are contained in the System.Trigger class.
Actions of Different Trigger Events
The following are lists of considerations about actions of different trigger events:
Trigger Event | Change fields using trigger.new | Update original object using an update DML operation | Delete original object using a delete DML operation |
beforeinsert | Allowed. | Not applicable. | Not applicable. |
afterinsert | Not allowed. A runtime error is thrown, as trigger.new is already saved. | Allowed. | Allowed, but unnecessary. The object is deleted immediately after being inserted. |
beforeupdate | Allowed. | Not allowed. A runtime error is thrown. | Not allowed. A runtime error is thrown. |
afterupdate | Not allowed. A runtime error is thrown, as trigger.new is already saved. | Allowed. | Allowed. |
beforedelete | Not allowed. A runtime error is thrown. trigger.new is not available before delete triggers. | Allowed. | Not allowed. |
afterdelete | Not allowed. A runtime error is thrown. trigger.new is not available after delete triggers. | Not applicable. The object has already been deleted. | Not applicable. The object has already been deleted. |
afterundelete | Not allowed. A runtime error is thrown. trigger.old is not available after undelete triggers. | Allowed. | Allowed, but unnecessary. The object is deleted immediately after being inserted. |
Before Insert Trigger
- In this case, the trigger will be fried when a new record will be saved in the database.
- In before insert, trigger. New stores a new list of records that will be inserted.
Example
Name duplication trigger on Contact (before insert, before update)
//this is the logic { Set<String> lastName = new Set<String>(); Set<String> setname = new Set<String>(); for(Contact cont : Trigger.new) { lastName.add(cont.email); } for(Contact cont : [SELECT lastName FROM Contact WHERE email in : lastName]) { setname.add(con.lastName); } if(Trigger.isInsert || Trigger.isUpdate) for(Contact a:trigger.new) { if(setname.contains(a.lastName)) { a.lastName.adderror('This email already exists'); } } }
After Insert
- This trigger will fire, after a new record is inserted successfully in the database.
- New is going to hold a new record inserted into the database.
- After insert trigger is read-only operation. We can do DML operations on new records inserted into the database.
Example
After Insert trigger on Account (after insert)
//this is the logic { for(Account acc: Trigger.new) { Account oldAcc = Trigger.oldMap.get(acc.Id); if(oldAcc.phone != acc.Phone) { List<Contact> contList = [SELECT Id, AccountId, Phone FROM Contact where AccountId = :acc.Id]; List<Contact> newids = new List<Contact>(); for(Contact con: contList) { if(con.Phone != acc.Phone) { con.Phone = acc.Phone; newids.add(con); } } if (!newids.isEmpty()) { update newids; } } } }
Update Trigger Events
There are two types of update events, that we are going to explain in detail:
- Before update
- After Update
Trigger. Old and Trigger. New are update events in Salesforce.
Before Update
- New: Trigger. New is going to hold the list of records which going to be updated.
- Old: Trigger. Old is going to hold the set of old values that will be updated.
It’s going to store the set record before updating it to the database.
Example
Before Update Trigger on Contact (before update)
//this is the logic { List<Account> acclist = new List<Account>(); for(Contact acc:trigger.old) { Account a = new Account(); c.Name=acc.Lastname; c.Phone=acc.Phone; acclist.add(a); } insert acclist; }
After Update
- The trigger will fire, only when the changes are made in the database.
- In the after update trigger operation we can only read the data from the trigger.
- If we want to make any changes, we need to perform DML operation.
Example
After Update trigger Contact on Account (after update)
//this is the logic { if(trigger.IsAfter && trigger.IsUpdate) { Set<Id> ids = new Set<Id>(); List<Contact> contlist = new List<Contact>(); for(account a:trigger.new) { ids.add(a.id); List<Contact> cont =[SELECT Id,Phone,LastName,Account.Phone FROM Contact WHERE AccountId in:ids]; for(Contact c:cont) { c.Phone = c.Account.Phone; contlist.add(c); } update contlist; } } }
Delete Event
There are two types of delete events, that we are going to explain:
- Before Delete
- After Delete
Before Delete (Trigger. Old)
The Trigger.Old will be holding the records that will be deleted. These records are read-only by the operation.
Example
Before Delete Trigger that deletes Account on Account (before delete)
//this is the logic { for(Account Acc:trigger.old) { acc.Name.addError('Account cannot be deleted'); } }
After Undelete ( Trigger.newMap and Trigger.oldMap )
- When we are undeleting records from the recycle bin after undeleting operation required.
- New is going to store the record which is undeleting from the recycle bin.
Trigger.oldMap
Trigger.oldMap is a map of IDs to the old version of the sObject records.
Example
Trigger Map on Account (before update)
//this is the logic { Map<Id,Account> accMap = new Map<Id,Account>(); accMap = trigger.oldMap; for(Account acc : trigger.new) { Account oldvalue = new Account(); oldvalue = accMap.get(acc.Id); if(acc.Phone != oldvalue.Phone) { acc.Phone.addError('Phone cannot be changed'); } } }
Trigger.newMap
Trigger.newMap is a map of IDs to the new version of the sObject records.
Example
Trigger update Phone Contact on Account (before update)
//this is the logic { if(trigger.isbefore && trigger.isupdate) { Map<Id,Account> mapcon= trigger.newmap; List<Contact> cont = new List<Contact>(); List<Contact> con = [SELECT Id,Phone,AccountId FROM Contact WHERE AccountId in : mapcon.keyset()]; for(Contact c : con) { c.Phone = mapcon.get(c.AccountId).Phone; cont.add(c); } update cont; } }
Summary
Apex triggers can help you to perform customized operations in the Salesforce database.
Want to learn more?
Read more about How to Write Good Requirements
Check out this Trail: Get Started With Apex Triggers
Share this article...
Pingback: How to define and initialize a Map, List, and Set with Apex |