Practical SQLite Workflows
Upsert Setting
Insert or Update
ON CONFLICT lets a workflow write a row whether the key is new or already present.
Program
Play the script to choose a theme value and update an existing setting through an upsert.
upsert_setting.sql
Replay: real traced execution (multi-file project)
CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT);
INSERT INTO settings VALUES ('theme', 'light'), ('page_size', '20');
WITH params(wanted_theme) AS (VALUES ('dark')) INSERT INTO settings(key, value) VALUES ('theme', (SELECT wanted_theme FROM params)) ON CONFLICT(key) DO UPDATE SET value = excluded.value;
SELECT key, value FROM settings ORDER BY key;
CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT);
INSERT INTO settings VALUES ('theme', 'light'), ('page_size', '20');
WITH params(wanted_theme) AS (VALUES ('light')) INSERT INTO settings(key, value) VALUES ('theme', (SELECT wanted_theme FROM params)) ON CONFLICT(key) DO UPDATE SET value = excluded.value;
SELECT key, value FROM settings ORDER BY key;
CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT);
INSERT INTO settings VALUES ('theme', 'light'), ('page_size', '20');
WITH params(wanted_theme) AS (VALUES ('contrast')) INSERT INTO settings(key, value) VALUES ('theme', (SELECT wanted_theme FROM params)) ON CONFLICT(key) DO UPDATE SET value = excluded.value;
SELECT key, value FROM settings ORDER BY key;
tables ← 1 row
1CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT);2INSERT INTO settings VALUES ('theme', 'light'), ('page_size', '20');values this step1 rowtablessettings ← 2 rows
1CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT);2INSERT INTO settings VALUES ('theme', 'light'), ('page_size', '20');3WITH params(wanted_theme) AS (VALUES ('dark')) INSERT INTO settings(key, value) VALUES ('theme', (SELECT wanted_theme FROM params)) ON CONFLICT(key) DO UPDATE SET value = excluded.value;values this step2 rowssettingssettings ← 2 rows
2INSERT INTO settings VALUES ('theme', 'light'), ('page_size', '20');3WITH params(wanted_theme) AS (VALUES ('dark')) INSERT INTO settings(key, value) VALUES ('theme', (SELECT wanted_theme FROM params)) ON CONFLICT(key) DO UPDATE SET value = excluded.value;4SELECT key, value FROM settings ORDER BY key;values this step2 rowssettingsresult ← 2 rows
3WITH params(wanted_theme) AS (VALUES ('dark')) INSERT INTO settings(key, value) VALUES ('theme', (SELECT wanted_theme FROM params)) ON CONFLICT(key) DO UPDATE SET value = excluded.value;4SELECT key, value FROM settings ORDER BY key;values this step2 rowsresult
tables ← 1 row
1CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT);2INSERT INTO settings VALUES ('theme', 'light'), ('page_size', '20');values this step1 rowtablessettings ← 2 rows
1CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT);2INSERT INTO settings VALUES ('theme', 'light'), ('page_size', '20');3WITH params(wanted_theme) AS (VALUES ('light')) INSERT INTO settings(key, value) VALUES ('theme', (SELECT wanted_theme FROM params)) ON CONFLICT(key) DO UPDATE SET value = excluded.value;values this step2 rowssettingssettings ← 2 rows
2INSERT INTO settings VALUES ('theme', 'light'), ('page_size', '20');3WITH params(wanted_theme) AS (VALUES ('light')) INSERT INTO settings(key, value) VALUES ('theme', (SELECT wanted_theme FROM params)) ON CONFLICT(key) DO UPDATE SET value = excluded.value;4SELECT key, value FROM settings ORDER BY key;values this step2 rowssettingsresult ← 2 rows
3WITH params(wanted_theme) AS (VALUES ('light')) INSERT INTO settings(key, value) VALUES ('theme', (SELECT wanted_theme FROM params)) ON CONFLICT(key) DO UPDATE SET value = excluded.value;4SELECT key, value FROM settings ORDER BY key;values this step2 rowsresult
tables ← 1 row
1CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT);2INSERT INTO settings VALUES ('theme', 'light'), ('page_size', '20');values this step1 rowtablessettings ← 2 rows
1CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT);2INSERT INTO settings VALUES ('theme', 'light'), ('page_size', '20');3WITH params(wanted_theme) AS (VALUES ('contrast')) INSERT INTO settings(key, value) VALUES ('theme', (SELECT wanted_theme FROM params)) ON CONFLICT(key) DO UPDATE SET value = excluded.value;values this step2 rowssettingssettings ← 2 rows
2INSERT INTO settings VALUES ('theme', 'light'), ('page_size', '20');3WITH params(wanted_theme) AS (VALUES ('contrast')) INSERT INTO settings(key, value) VALUES ('theme', (SELECT wanted_theme FROM params)) ON CONFLICT(key) DO UPDATE SET value = excluded.value;4SELECT key, value FROM settings ORDER BY key;values this step2 rowssettingsresult ← 2 rows
3WITH params(wanted_theme) AS (VALUES ('contrast')) INSERT INTO settings(key, value) VALUES ('theme', (SELECT wanted_theme FROM params)) ON CONFLICT(key) DO UPDATE SET value = excluded.value;4SELECT key, value FROM settings ORDER BY key;values this step2 rowsresult
Follow the Upsert
settingsstarts withtheme=lightandpage_size=20.wanted_themeisdark.- The insert tries to write key
theme. themealready exists, soON CONFLICTupdates its value.- The final ordered rows are
page_size 20andtheme dark. | wanted_theme | existing theme | final theme | final ordered rows | | --- | --- | --- | --- | | dark | light | dark | page_size 20; theme dark | | light | light | light | page_size 20; theme light | | contrast | light | contrast | page_size 20; theme contrast |
ON CONFLICT
`ON CONFLICT(key)` handles the duplicate primary-key case.
excluded
`excluded.value` is the value the insert tried to write.
idempotent workflow
Running the same shape of write can create or update the target row.
Exercise: upsert_setting.sql
Reproduce page_size 20 and theme dark, then use wanted_theme light and contrast to predict the final theme row.