Sequences¶
PostgreSQL sequences generate unique numeric identifiers, commonly used for auto-incrementing primary keys.
PostgreSQL Specification¶
CREATE SEQUENCE Syntax¶
CREATE [ TEMPORARY | TEMP ] SEQUENCE [ IF NOT EXISTS ] name
[ AS data_type ]
[ INCREMENT [ BY ] increment ]
[ MINVALUE minvalue | NO MINVALUE ]
[ MAXVALUE maxvalue | NO MAXVALUE ]
[ START [ WITH ] start ]
[ CACHE cache ]
[ [ NO ] CYCLE ]
[ OWNED BY { table_name.column_name | NONE } ]
Reference: PostgreSQL 17 CREATE SEQUENCE
pgdelta Support¶
✅ Currently Supported¶
- CREATE SEQUENCE with all options
- DROP SEQUENCE
- ALTER SEQUENCE OWNED BY
- All sequence parameters (INCREMENT, MINVALUE, MAXVALUE, START, CACHE, CYCLE)
CREATE SEQUENCE "public"."users_id_seq"
AS bigint
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START WITH 1
CACHE 1
NO CYCLE;
ALTER SEQUENCE "public"."users_id_seq" OWNED BY "public"."users"."id";
❌ Not Yet Supported¶
- ALTER SEQUENCE parameter modifications (planned)
- RESTART operations (planned)
🚫 Intentionally Not Supported¶
- TEMPORARY sequences (not persistent schema objects)
- IF EXISTS/IF NOT EXISTS (pgdelta tracks existence)
Usage Examples¶
Basic Sequence¶
target_sql = """
CREATE SEQUENCE user_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
"""
Sequence with Table¶
target_sql = """
CREATE SEQUENCE user_id_seq;
CREATE TABLE users (
id BIGINT DEFAULT nextval('user_id_seq') PRIMARY KEY,
email TEXT NOT NULL
);
ALTER SEQUENCE user_id_seq OWNED BY users.id;
"""
SERIAL Columns (Auto-generated Sequences)¶
target_sql = """
CREATE TABLE users (
id SERIAL PRIMARY KEY, -- Creates users_id_seq automatically
email TEXT NOT NULL
);
"""
# pgdelta handles the auto-generated sequence
Implementation Details¶
Sequence Models¶
@dataclass(frozen=True)
class CreateSequence:
stable_id: str # Format: "s:schema.sequence_name"
namespace: str # Schema name
seqname: str # Sequence name
sequence_definition: str # Complete sequence definition
owned_by: str | None # Table.column ownership
SQL Generation¶
def generate_create_sequence_sql(change: CreateSequence) -> str:
"""Generate CREATE SEQUENCE SQL."""
sql_parts = [change.sequence_definition]
# Add ownership if specified
if change.owned_by:
quoted_seq = f'"{change.namespace}"."{change.seqname}"'
sql_parts.append(f"ALTER SEQUENCE {quoted_seq} OWNED BY {change.owned_by};")
return "\n".join(sql_parts)
Sequence Parameters¶
Data Types¶
-- Integer sequences (default)
CREATE SEQUENCE int_seq AS integer;
-- Bigint sequences (for large ranges)
CREATE SEQUENCE bigint_seq AS bigint;
-- Smallint sequences (for small ranges)
CREATE SEQUENCE smallint_seq AS smallint;
Increment Options¶
-- Increment by 1 (default)
CREATE SEQUENCE normal_seq INCREMENT BY 1;
-- Increment by 10
CREATE SEQUENCE skip_seq INCREMENT BY 10;
-- Decrement (negative increment)
CREATE SEQUENCE countdown_seq INCREMENT BY -1 START WITH 1000;
Range Options¶
-- Custom range
CREATE SEQUENCE custom_range_seq
MINVALUE 1000
MAXVALUE 9999
START WITH 1000;
-- No limits
CREATE SEQUENCE unlimited_seq
NO MINVALUE
NO MAXVALUE;
Caching and Cycling¶
-- High performance with caching
CREATE SEQUENCE cached_seq CACHE 100;
-- Cycling sequence
CREATE SEQUENCE cycling_seq
MINVALUE 1
MAXVALUE 100
CYCLE;
Future Enhancements¶
Planned Features (v0.2.0)¶
- ALTER SEQUENCE support
- Sequence value synchronization
- Identity column integration
Best Practices¶
Sequence Naming¶
# Good sequence names
good_names = [
"users_id_seq", # Table + column + seq
"order_number_seq", # Business identifier
"invoice_seq", # Short and clear
]
# Avoid generic names
avoid_names = [
"seq1", "sequence", # Non-descriptive
"my_seq", "temp_seq", # Unclear purpose
]
Sequence Design¶
# Sequence design considerations
design_considerations = {
"data_type": "Use BIGINT for high-volume tables",
"increment": "Usually 1, higher for bulk operations",
"cache": "Higher cache for better performance",
"cycle": "Rarely needed, consider implications",
"ownership": "Always set OWNED BY for dependent sequences"
}
# Performance tips
performance_tips = {
"cache_size": "Increase cache for high-throughput sequences",
"multiple_sequences": "Use separate sequences for different purposes",
"avoid_gaps": "Gaps are normal and expected in sequences"
}
Common Patterns¶
# Standard SERIAL pattern
serial_pattern = """
CREATE TABLE table_name (
id SERIAL PRIMARY KEY, -- Auto-creates sequence
-- other columns
);
"""
# Custom sequence pattern
custom_pattern = """
CREATE SEQUENCE table_name_id_seq
START WITH 1
INCREMENT BY 1
CACHE 1;
CREATE TABLE table_name (
id BIGINT DEFAULT nextval('table_name_id_seq') PRIMARY KEY,
-- other columns
);
ALTER SEQUENCE table_name_id_seq OWNED BY table_name.id;
"""