Trying to create a trigger that will update a field if an attachment related to it is added or deleted.

Here's what I have so far

trigger updateAttachments on ContentDocumentLink (after insert, after delete) {
    List<Opportunity> Opps = new List<Opportunity>();
        for(ContentDocumentLink c: Trigger.New){
            Opps = [SELECT id, hasAttachment__C from Opportunity WHERE id =: c.LinkedEntityId];
        for(Opportunity o: Opps){
            o.hasAttachment__c = True;
        for(ContentDocumentLink d:Trigger.Old){
            Opps = [SELECT id, hasAttachment__C from Opportunity WHERE id =: d.LinkedEntityId];
        for(Opportunity op: Opps){
            op.hasAttachment__c = False;
    update Opps;

The trigger is working when adding a new record, the problem is when I delete an attachment the checkbox does not update.

Please give me an insight on why it's not getting triggered when I delete an attachment

Thank you!

1 Answer 1


This logic is broken to begin with. It presumes that the opportunity only has one record. It's also not bulkified properly, queries inside loops, etc. Here's a revised version:

trigger updateAttachments on ContentDocumentLink (after insert, after delete) {
    // See if we have opportunities to update
    Map<Id, Opportunity> opps = new Map<Id, Opportunity>();
    for(ContentDocumentLink record: Trigger.isInsert? Trigger.new: Trigger.old) {
        if(record.LinkedEntityId?.getSObjectType() == Opportunity.sObjectType) {
            opps.put(record.LinkedEntityId, new Opportunity(Id=record.LinkedEntityId,hasAttachment__C=false));
    if(opps.isEmpty()) {
        return; // Nothing to do
    // Find attachments for each opportunity with at least one record
    Set<Id> oppsWithAttachments = new Map<Id, AggregateQueryResult>([
        SELECT LinkedEntityId Id
        FROM ContentDocumentLink
        WHERE LinkedEntityId = :opps.keySet()
        GROUP BY LinkedEntityId
    // Proposed record updates
    for(Opportunity record: opps.values()) {
        record.hasAttachment__c = oppsWithAttachments.contains(record.Id);
    // Check to see if update is neessary
    for(Opportunity record: [SELECT hasAttachment__c FROM Opportunity WHERE Id = :opps.keySet()]) {
        if(record.hasAttachment__c == opps.get(record.Id)) {
    // Update all records that need to change
    update opps.values();

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .