Search code examples
sqliteviewtriggersatomicrowid

Sqlite: Are updates to two tables within an insert trigger atomic?


I refactored a table that stored both metadata and data into two tables, one for metadata and one for data. This allows metadata to be queried efficiently.

I also created an updatable view with the original table's columns, using sqlite's insert, update and delete triggers. This allows calling code that needs both data and metadata to remain unchanged.

The insert and update triggers write each incoming row as two rows - one in the metadata table and one in the data table, like this:

// View
CREATE VIEW IF NOT EXISTS Item as select n.Id, n.Title, n.Author, c.Content 
FROM ItemMetadata n, ItemData c where n.id = c.Id

// Trigger
CREATE TRIGGER IF NOT EXISTS item_update 
INSTEAD OF UPDATE OF  id, Title, Author, Content ON Item
BEGIN

UPDATE ItemMetadata 
SET Title=NEW.Title, Author=NEW.Author
WHERE Id=old.Id;

UPDATE ItemData SET Content=NEW.Content
WHERE Id=old.Id;

END;

Questions:

  • Are the updates to the ItemMetadata and ItemData tables atomic? Is there a chance that a reader can see the result of the first update before the second update has completed?
  • Originally I had the WHERE clauses be WHERE rowid=old.rowid but that seemed to cause random problems so I changed them to WHERE Id=old.Id. The original version was based on tutorial code I found. But after thinking about it I wonder how sqlite even comes up with an old rowid - after all, this is a view across multiple tables. What rowid does sqlite pass to an update trigger, and is the WHERE clause the way I first coded it problematic?

Solution

  • The documentation says:

    No changes can be made to the database except within a transaction. Any command that changes the database (basically, any SQL command other than SELECT) will automatically start a transaction if one is not already in effect.

    Commands in a trigger are considered part of the command that triggered the trigger. So all commands in a trigger are part of a transaction, and atomic.

    Views do not have a (usable) rowid.