CREATE SEQUENCE
Turso Extension: CREATE SEQUENCE is a Turso-specific statement not available in standard SQLite.
nextval(), currval(), and setval() functions.
Syntax
Description
A sequence generates a series of integer values according to its configuration. Each call tonextval() produces the next value in the series. Sequences are persisted in the database schema and survive restarts.
Unlike AUTOINCREMENT on an INTEGER PRIMARY KEY, sequences are standalone objects. A single sequence can supply values to multiple tables, or multiple sequences can feed into different columns of the same table.
Parameters
Validation
The following rules are enforced at creation time:INCREMENT BYmust not be zero.MINVALUEmust be less thanMAXVALUE.- For ascending sequences (
INCREMENT > 0):STARTmust be greater than or equal toMINVALUE. - For descending sequences (
INCREMENT < 0):STARTmust be less than or equal toMAXVALUE.
Sequence Functions
nextval()
Returns the next value from the sequence and advances it.nextval() returns the START value. Each subsequent call increments by INCREMENT BY.
Sequence persistence under WAL mode is transactional: the sequence backing-table update is committed or rolled back with the transaction that called nextval(). Under MVCC mode (journal_mode=experimental_mvcc) inside BEGIN CONCURRENT, the backing-table write is autonomous and survives an outer ROLLBACK (postgres-like). For BEGIN / BEGIN IMMEDIATE / autocommit, the inner write is bundled with the outer and rolls back with it (SQLite-like).
Turso does not guarantee gap-free sequences, and it also does not guarantee PostgreSQL-style permanent burning of values from rolled-back transactions in WAL mode or under an exclusive (BEGIN IMMEDIATE / BEGIN DEFERRED) MVCC outer.
If a transaction calls nextval() and rolls back, that value may be generated again later if no committed transaction used that value or a later value. If another concurrent transaction commits after allocating a later value, the rolled-back value can remain a gap. The guarantee is that persisted sequence state remains consistent with committed database state.
currval()
Returns the last value returned bynextval() in the current connection. Raises an error if nextval() has not been called on this sequence in the current session.
setval()
Sets the sequence to an explicit value.Examples
Basic Sequence
Custom Start and Increment
Descending Sequence
Cycling Sequence
When the sequence reaches its boundary, it wraps around:CYCLE, exceeding the boundary raises an error:
Sequence as Column Default
A sequence can supply default values for a table column:IF NOT EXISTS
Concurrency
nextval() and setval() persist sequence state to a backing table.
In WAL mode (the default), the backing-table write rides on the caller’s
write transaction. Only one connection can hold the write lock at a time; if
another connection is already writing, SELECT nextval(...) will return
SQLITE_BUSY (“Database is busy”). This is different from AUTOINCREMENT,
which uses a process-local allocator and writes the committed watermark with
the table insert.
In MVCC mode (journal_mode=experimental_mvcc), nextval() inside a
BEGIN CONCURRENT outer wraps the backing-table write in an autonomous inner
transaction that commits immediately and independently of the outer’s eventual
commit or rollback. This lets multiple concurrent BEGIN CONCURRENT callers
each get a fresh value (serialized by the standard MVCC PK conflict + bounded
retry on the backing table), and matches PostgreSQL’s “burnt value” semantics
for this case. For autocommit, BEGIN, BEGIN IMMEDIATE, and BEGIN DEFERRED,
the outer holds the exclusive lock and the inner write runs inline — under
those modes a ROLLBACK un-burns the value (SQLite-like).
In rollback cases, generated values are not guaranteed to be reused and are
not guaranteed to remain gaps. Reuse depends on the outer transaction mode
and on whether another committed transaction advanced the durable watermark
past that value.
If your workload calls nextval() from many concurrent connections in WAL
mode, consider using AUTOINCREMENT instead, or serializing sequence access
at the application level.
Recovering the current value
The “current value” reachable from a fresh connection depends on mode:-
WAL mode: read
seqfromsqlite_sequence(for AUTOINCREMENT tables) or query the sequence backing table directly:Both are kept in sync at commit time. -
MVCC mode:
sqlite_sequenceis updated only at checkpoint time — between checkpoints it may lag the actual high-water mark or be empty for a freshly-created AUTOINCREMENT table. Do not rely onsqlite_sequenceto recover the live value in MVCC mode. Instead, query the internal sequence backing table directly:For AUTOINCREMENT, the sequence name is__turso_internal_autoincrement_<table>, so the backing-table query becomes:AfterPRAGMA wal_checkpoint(TRUNCATE), the backing table is coalesced to a single row andsqlite_sequenceis also brought up to date with exactly one row per AUTOINCREMENT table — at that point both are safe to read with normal SQLite-compatible queries.
Errors
See Also
- DROP SEQUENCE for removing sequences
- CREATE TABLE for
AUTOINCREMENTonINTEGER PRIMARY KEYcolumns