I have an SQLite3 database which, in order to optimize performance, uses computed columns kept up to date by triggers.
I'm now trying to add a trigger which would be analogous to this (untested but probably valid) SQLAlchemy ORM code
story.read_free = any(link.link_type.read_free for link in story.links)
...but I'm having trouble figuring out how to express that as an UPDATE
clause. Here's what I've got so far:
CREATE TRIGGER IF NOT EXISTS update_link_type AFTER UPDATE ON link_types
FOR EACH ROW WHEN old.read_free <> new.read_free BEGIN
UPDATE stories SET
read_free = CASE WHEN (
SELECT 1 FROM links as l, link_types as lt WHERE lt.id = new.id AND l.link_type_id = lt.id AND l.story_id = stories.id
) THEN 1 ELSE 0 END
WHERE id = (SELECT story_id from links as l, link_types as lt WHERE l.link_type_id = lt.id AND lt.id = new.id)
;
END;
My specific problem is that I can't figure out how to ensure that the subquery in the CASE
is correlated.
Either SQLite rejects the syntax (things like UPDATE foo AS bar
and UPDATE INNER JOIN ...
which are apparently how you do it on other DBs) or, as in the example I gave, it's valid, but has the wrong meaning. (In this case, "Set read_free on this story if there exists any link type with read_free, whether or not the story has links of that type)
If a more clean, concise phrasing of that UPDATE
exists beyond simply fixing the problem, I'd also appreciate knowing it. Even if that did work, it'd be a very ugly solution compared to the worst of the rest of my triggers.