Chapter 03 · SQLite Schema Objects, ROWID, Keys, and Table Design

Temporary Tables, In-Memory Databases, and the temp Schema

Separate connection-scoped TEMP objects from entire in-memory databases, then prove what survives across connections and what disappears.

Beginner75–95 minutesPersistence boundary labSQLite 3.53.4 baselineLast reviewed: August 2026

Learning outcomes

“Temporary” and “in memory” sound similar, but SQLite uses them for different scopes. A TEMP table is an object in a connection-private temp schema. An entire :memory: database is a database whose main storage exists only for the lifetime of its connection. Mixing those concepts leads to disappearing data and confusing tests.

01

Explain the persistence boundary of a :memory: main database.

02

Distinguish TEMP tables from an entire in-memory database and from temporary files used internally.

03

Use main, temp, and an attached schema intentionally.

04

Explain when named/shared in-memory databases can be shared and why they remain process/lifetime scoped.

05

Build a lab that closes connections and proves exactly which objects survive.

:memory: replaces the main database with connection-lifetime state

If the database filename is exactly :memory:, SQLite creates a private in-memory database for that connection. Nothing is written to a normal database file, and the database disappears when the connection closes.

text · prove :memory: lifetime
sqlite3 :memory:CREATE TABLE demo (    id INTEGER PRIMARY KEY,    note TEXT NOT NULL);INSERT INTO demo(note) VALUES ('exists only in this connection');SELECT * FROM demo;.databases.quit-- Start a new process/connection:sqlite3 :memory:.tables

The second session has no demo table. That is not data loss; it is the requested lifetime. This makes :memory: excellent for isolated tests and scratch computation where persistence would be undesirable.

Exact-name rule

The special pure-memory behavior applies to the exact special filename :memory:. A pathname such as ./:memory: is an ordinary disk filename, not the special in-memory database.

A TEMP table is a schema choice, not a synonym for RAM

CREATE TEMP TABLE creates an object in the connection's temp schema. That schema is private to the connection and destroyed when the connection closes. SQLite may back temporary structures with memory or temporary files depending on build/runtime configuration, so “TEMP table” describes visibility and lifetime more reliably than physical medium.

text · main versus temp
sqlite3 chapter03_scope.dbCREATE TABLE main.persistent_note (    id INTEGER PRIMARY KEY,    note TEXT NOT NULL);CREATE TEMP TABLE scratch_note (    id INTEGER,    note TEXT);INSERT INTO main.persistent_note(note) VALUES ('survives reconnect');INSERT INTO temp.scratch_note VALUES (1, 'connection only');SELECT * FROM main.persistent_note;SELECT * FROM temp.scratch_note;PRAGMA temp_store;.databases

PRAGMA temp_store reports a storage policy setting; compile-time option SQLITE_TEMP_STORE can influence the effective behavior. Do not change it just to complete this lesson. The essential guarantee is that the temp schema is connection-private and disappears on close.

main, temp, and attached databases are schemas on one connection

An SQLite connection can address more than one database. The primary database is main. The connection-private temporary database is temp. ATTACH DATABASE adds another database under a name you choose.

sql · three schemas on one connection
ATTACH DATABASE 'chapter03_archive.db' AS archive;CREATE TABLE archive.archived_note (    archive_id INTEGER PRIMARY KEY,    note TEXT NOT NULL);SELECT 'main' AS schema_name, nameFROM main.sqlite_schemaWHERE type='table'UNION ALLSELECT 'temp', nameFROM temp.sqlite_schemaWHERE type='table'UNION ALLSELECT 'archive', nameFROM archive.sqlite_schemaWHERE type='table'ORDER BY schema_name, name;DETACH DATABASE archive;

Schema qualification becomes important when the same object name could exist in more than one database. It also makes scripts self-documenting: main.device means durable application state, while temp.stage_device announces a connection-scoped staging object.

Atomicity preview

Transactions that span attached databases have additional journaling/WAL caveats. Chapter 8–9 covers transaction and WAL semantics; this lesson uses ATTACH only to teach names and visibility.

Named/shared in-memory databases are a specialized same-process technique

SQLite supports URI filenames such as file:memdb1?mode=memory&cache=shared. Two connections can share that named in-memory database only when URI processing is enabled, the URI name matches, and the connections are in the same process participating in the shared cache. The database disappears when the last participating connection closes.

text · shared-memory lifetime model
# Application-level concept, not two independent shell processes:connection A -> file:fieldnotes_mem?mode=memory&cache=sharedconnection B -> file:fieldnotes_mem?mode=memory&cache=sharedsame process + same URI name + shared cache              |              v       one named in-memory database              |      deleted after last close

Do not use two separate terminal sqlite3 processes as proof of shared memory; separate processes do not share this in-memory database. Also record URI support/flags in application code instead of assuming every host wrapper enables URI processing identically.

Modern guidance

SQLite documentation says shared-cache mode is generally discouraged for new designs; WAL is usually the better concurrency mechanism when sharing a file. Named shared-memory databases remain useful for specialized same-process tests and caches, not as a substitute for a network database server.

Persistence matrix: choose by required lifetime

Storage/objectVisible toSurvives connection close?Typical use
Table in disk-backed mainConnections that open the file with appropriate accessYesApplication state, durable tests, local databases
TEMP table / temp schemaOnly the creating connectionNoScratch transforms, staging, per-connection caches
:memory: main databaseThat one connectionNoUnit tests, disposable experiments
Named shared in-memory URIParticipating connections in same process/configurationUntil the last participating connection closesSpecialized same-process shared test/cache
Attached disk databaseThe connection while attached; durable file itself can be reopenedYes, file survives detach/closeArchive, migration, cross-file workflows

Lab: prove what survives by closing the connection

This lab intentionally uses both a disk-backed main database and a TEMP table. The close/reopen step is the test.

text · close/reopen proof
sqlite3 chapter03_scope.dbDROP TABLE IF EXISTS main.survival_test;CREATE TABLE main.survival_test (    id INTEGER PRIMARY KEY,    note TEXT NOT NULL);CREATE TEMP TABLE disappearance_test (    id INTEGER,    note TEXT);INSERT INTO main.survival_test(note) VALUES ('disk-backed main');INSERT INTO temp.disappearance_test VALUES (1, 'temp schema');SELECT * FROM main.survival_test;SELECT * FROM temp.disappearance_test;.quitsqlite3 chapter03_scope.dbSELECT * FROM main.survival_test;SELECT * FROM temp.disappearance_test;

After reconnect, main.survival_test returns its row because the table and row are in the database file. The query against temp.disappearance_test should fail with “no such table” because the original connection's temp schema was destroyed.

text · whole-database lifetime proof
sqlite3 :memory:CREATE TABLE main.memory_only(id INTEGER PRIMARY KEY, note TEXT);INSERT INTO memory_only(note) VALUES ('gone after close');SELECT COUNT(*) FROM memory_only;.quitsqlite3 :memory:SELECT COUNT(*) FROM memory_only;

The second :memory: connection should report that memory_only does not exist. This experiment proves the difference between a durable file, a temporary schema, and an in-memory main database.

Lifetime checkpoint

Name both the storage scope and the visibility scope.

  1. Why does a TEMP table disappear even when main uses a disk file?
  2. Why is :memory: different from CREATE TEMP TABLE?
  3. Can two separate OS processes share a named in-memory database using cache=shared?
  4. What does archive.table_name mean after ATTACH?
  5. Why should you avoid assuming TEMP means “physically RAM-backed”?
Review the answers

The temp schema belongs to the connection rather than the main file; :memory: makes the entire main database connection-lifetime whereas TEMP affects selected objects; named shared-memory databases are same-process facilities rather than cross-process servers; archive is the schema name assigned to an attached database; and temporary storage may be memory or a temporary file depending on runtime/compile settings.

Failure patterns and safe corrections

SymptomLikely causeCorrection
Test data vanished after process exit.Database was opened as :memory:.Use a named disk file when persistence is part of the test.
TEMP staging table missing in another connection.TEMP schema is connection-private.Keep staging and transformation on the same connection or use a deliberately shared durable/staging design.
A file named :memory: unexpectedly appeared.A pathname such as ./:memory: was used.Use the exact special name :memory: for pure memory.
Attached object resolved ambiguously.Same object name exists in multiple schemas.Use schema-qualified names such as main.device.
Shared-memory test fails across two CLI processes.Named shared in-memory databases do not span independent processes.Test sharing with multiple connections inside one process, or use a disk-backed database.

Summary and bridge to deliberate schema design

You can now separate three independent design questions: what key organizes rows, which schema owns an object, and how long the database/object lives. That vocabulary is enough to design the FieldNotes schema deliberately rather than copy generic SQL DDL. Lesson 5 combines rowid choices, a composite WITHOUT ROWID table, constraints, and introspection into a reusable schema review.

References

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only assets compatible with the Ethereum/ERC-20 network. Do not send TRC-20/TRON assets.