diff --git a/sql/swh-archiver-schema.sql b/sql/swh-archiver-schema.sql
index d6f7f1647117f9384776332e806081f201fde4fe..aac607eb2e87c8dc2bfa7d43c978e30d780e69b9 100644
--- a/sql/swh-archiver-schema.sql
+++ b/sql/swh-archiver-schema.sql
@@ -11,7 +11,7 @@ create table dbversion
 comment on table dbversion is 'Schema update tracking';
 
 INSERT INTO dbversion(version, release, description)
-VALUES(7, now(), 'Work In Progress');
+VALUES(8, now(), 'Work In Progress');
 
 CREATE TABLE archive (
   id text PRIMARY KEY
@@ -74,7 +74,7 @@ CREATE TRIGGER update_num_present
     EXECUTE PROCEDURE update_num_present();
 
 -- keep the content_archive_counts updated
-CREATE FUNCTION update_content_archive_counts() RETURNS TRIGGER LANGUAGE PLPGSQL AS $$
+CREATE OR REPLACE FUNCTION update_content_archive_counts() RETURNS TRIGGER LANGUAGE PLPGSQL AS $$
     DECLARE
         content_id sha1;
         content_bucket bucket;
@@ -104,7 +104,7 @@ CREATE FUNCTION update_content_archive_counts() RETURNS TRIGGER LANGUAGE PLPGSQL
             from jsonb_each(old_row.copies) o full outer join lateral jsonb_each(new_row.copies) n on o.key = n.key
       LOOP
         -- the count didn't change
-        CONTINUE WHEN copies.old_status is distinct from copies.new_status OR
+        CONTINUE WHEN copies.old_status is not distinct from copies.new_status OR
                       (copies.old_status != 'present' AND copies.new_status != 'present');
 
         update content_archive_counts cac
diff --git a/sql/upgrades/008.sql b/sql/upgrades/008.sql
new file mode 100644
index 0000000000000000000000000000000000000000..6527aca69198f105433105fbea182497a42878b7
--- /dev/null
+++ b/sql/upgrades/008.sql
@@ -0,0 +1,49 @@
+-- SWH DB schema upgrade
+-- from_version: 7
+-- to_version: 8
+-- description: Fix silly bug in update_content_archive_counts
+
+INSERT INTO dbversion(version, release, description)
+VALUES(8, now(), 'Work In Progress');
+
+-- keep the content_archive_counts updated
+CREATE OR REPLACE FUNCTION update_content_archive_counts() RETURNS TRIGGER LANGUAGE PLPGSQL AS $$
+    DECLARE
+        content_id sha1;
+        content_bucket bucket;
+        copies record;
+        old_row content_archive;
+        new_row content_archive;
+    BEGIN
+      -- default values for old or new row depending on trigger type
+      if tg_op = 'INSERT' then
+          old_row := (null::sha1, '{}'::jsonb, 0);
+      else
+          old_row := old;
+      end if;
+      if tg_op = 'DELETE' then
+          new_row := (null::sha1, '{}'::jsonb, 0);
+      else
+          new_row := new;
+      end if;
+
+      -- get the content bucket
+      content_id := coalesce(old_row.content_id, new_row.content_id);
+      content_bucket := substring(content_id from 19)::bucket;
+
+      -- compare copies present in old and new row for each archive type
+      FOR copies IN
+        select coalesce(o.key, n.key) as archive, o.value->>'status' as old_status, n.value->>'status' as new_status
+            from jsonb_each(old_row.copies) o full outer join lateral jsonb_each(new_row.copies) n on o.key = n.key
+      LOOP
+        -- the count didn't change
+        CONTINUE WHEN copies.old_status is not distinct from copies.new_status OR
+                      (copies.old_status != 'present' AND copies.new_status != 'present');
+
+        update content_archive_counts cac
+            set count = count + (case when copies.old_status = 'present' then -1 else 1 end)
+            where archive = copies.archive and bucket = content_bucket;
+      END LOOP;
+      return null;
+    END;
+$$;