SQLite Forum

Main Topic and Non Main Topics (Was: Topic and subtopic)
Login
Ok, so here we are, somewhat simpler.  Uses a rowid table for the DataTopics.  It will ensure that there is always an IsMain==1 for every record.  If you do something such that this becomes untrue, the "oldest" topic becomes the main topic.  All the "management" of IsMain is "automagic" if you leave it out of insert statements, and if you specify it (as is specify IsMain = 1) then that will have "force" and previous IsMain for that Data will be reset.

```
create table Topic
(
  id     integer primary key,
  name   text collate nocase unique
);

create table Data
(
  id          integer primary key
  -- other data
);

create table DataTopics
(
  DataID     integer not null references Data(id),
  TopicID    integer not null references Topic(id),
  IsMain     integer not null on conflict replace default 0 check (IsMain in (0, 1)),
  PRIMARY KEY (DataID, TopicID),
  UNIQUE (TopicID, DataID)
);
create index MainDataTopics on DataTopics(DataID) where IsMain == 1;

-- if inserting ismain == 0 (default) change inserted record to ismain == 1 if there is no IsMain == 1 record
create trigger DataTopicsInsert0 after insert on DataTopics when new.IsMain == 0
begin
  update DataTopics
     set IsMain == 1
   where DataID == new.DataID
     and TopicID == new.TopicID
     and not exists (
                     select 1
                       from DataTopics
                      where DataID == new.DataID
                        and IsMain == 1
                    );
end;

-- if inserting ismain == 1 change previous ismain to 0
create trigger DataTopicsInsert1 after insert on DataTopics when new.IsMain == 1
begin
  update DataTopics
     set IsMain == 0
   where DataID == new.DataID
     and TopicID != new.TopicID
     and IsMain == 1;
end;

-- when changing to IsMain == 1 then reset any other IsMain == 1 to 0
create trigger DataTopicsUpdate1 after update on DataTopics when old.IsMain == 0 and new.IsMain == 1
begin
  update DataTopics
     set IsMain = 0
   where DataID == new.DataID
     and TopicID != new.TopicID
     and IsMain == 1;
end;

-- when changing to IsMain == 0 make sure we have an IsMain, if not use the oldest one
create trigger DataTopicUpdate0 after update on DataTopics when old.IsMain == 1 and new.IsMain == 0
begin
  update DataTopics
     set IsMain = 1
   where RowID == (
                      select min(rowid)
                        from DataTopics
                       where DataID == old.DataID
                    order by rowid
                       limit 1
                  )
     and not exists (
                     select 1
                       from DataTopics
                      where DataID == new.DataID
                        and IsMain == 1
                    );
end;

-- Make sure we always have IsMain record after a delete
create trigger DataTopicsDelete after delete on DataTopics when old.IsMain == 1
begin
  update DataTopics
     set IsMain = 1
   where RowID == (
                      select min(rowid)
                        from DataTopics
                       where DataID == old.DataID
                    order by rowid
                       limit 1
                  );
end;
```

Note that the previous versions may not work correctly because they included IsMain in the unique indexes and it should not have been.  Sorry 'bout that.  It also works with recursive triggers turned on.