You could do a quick comparison with a Set
operation.
You could simply go:
Set<sObject> oldRecordSet = new Set<sObject>(Trigger.Old.deepClone(true, true, true));
oldRecordSet.removeAll(Trigger.New);
Integer numberOfChanges = oldRecordSet.size();
If the number is 0, there were no changes. Otherwise, you have the number of changes.
If there were changes, you can then get the Ids of the records that did change like this:
Set<Id> changedRecordIdSet = (new Map<Id, sObject>(new List<sObject>(oldRecordSet))).keySet();
I haven't tested it yet, but I believe this will work.
Edit
There's one issue with doing this approach. It will always return Trigger.New
if you think about it. Even if you checked all fields that could be editable, there are always fields that will be edited, like the LastModified
date.
LastModifiedDate
is always updated, so this comparison would always catch the entire list.