SQLite

Created: 16 Mar 2024
Updated: 25 Sep 2025
sqlite.png
home https://sqlite.org/
source (C) https://www.sqlite.org/src/doc/trunk/README.md
faq https://www.sqlite.org/faq.html
wiki https://en.wikipedia.org/wiki/SQLite
gotchas https://sqlite.org/quirks.html

cli

$ sqlite3 :memory: # or just not pass any argument
$ sqlite3 foo.db 'SELECT * FROM events'
$ sqlite3 foo.db '.dump'

flag

-csv   .mode
-html   .mode
-column   .mode
-list   .mode
-line   .mode
-vfs S  
-[no]header   .headers on/off
-separator S .separator S
-cmd S run command
-bail   exit on error

metacomands

  ARGUMENT DESCRIPTION
.bail on/off exits on error (also -bail)
.dump [TABLEPAT] sql dump whole db or table
.headers on/off toggle header display
.schema [TABLEPAT] shows schema of whole db or table
.show - shows settings
.stats - session? stats
.timer on/off show runtime after queries
.import –csv foo.csv bar import csv file into "bar" table
.tables - list all tables
.load EXNAME loads an extension
.open DBFILE opens database when non was already opened
.save DBFILE write in-memory db into FILE
.separator "¦" change the separator for ".mode list"
.eqp on/off/full explain query planner
.output FILE redirects output to FILE
.output stdout resets output
.mode   change output format
  list DEFAULT
  csv  
  tabs aka tsv
  json returns an array of json objects
  insert [TNAME] sql INSERT statements
  html html <table> code
  markdown  
  ascii ??? broken ???
  line human? vertical, one column per line
  column human readable, ascii table
  box human readable, utf8 table
  –wrap N some modes accept a max length to wrap, default 0
PRAGMA compile_options; show sqlite's compile options
PRAGMA journal_mode=WAL useful for concurrent writes
PRAGMA busy_timeout=5000 how long a write transaction will wait
PRAGMA foreign_keys=ON disabled by default

language

Types

INTEGER includes literals true/false which map to 1/0
REAL floating point numbers
TEXT readable text
BLOB binary data
NULL no data

Command

  • CREATE [TEMP] TABLE [IF NOT EXISTS] tname
  • CREATE [UNIQUE] INDEX [IF NOT EXISTS] iname ON tname
  • DROP [INDEX|TABLE|TRIGGER|VIEW] [IF EXISTS] name
  • INSERT
  • LIMIT row_count
  • LIMIT row_count OFFSET offset
  • LIMIT offset, row_count
  • CASE WHEN expr THEN
  • CASE expr WHEN expr THEN res
    • ELSE res
  • END

Stdlib Functions

Core

https://www.sqlite.org/lang_corefunc.html

FUNCTION ARGS DESCRIPTION
char uc1,uc2,… build a string of unicode codes passed as ints
concat x ,… concatenates non-null args (aka "¦¦")
concat_ws sep, x, … concatenates non-null args with SEP
format fmt,… aka printf()
instr x ,y position of y in x
length x  
lower x ascii only by default, load ICU extension for other
upper x ascii only
ltrim x[,y]  
rtrim x[,y]  
trim x[,y]  
replace x ,y ,z replaces y by z in x
substr[ing] x ,y[,z] starting at y for z length
unicode x unicode for first char in x
glob pat,col like GLOB, which is like LIKE, but globbing
like x ,y  
  x ,y ,z  
coalesce x,y,… returns first non-null arg (ME: lisp or)
ifnull x,y returns first non-null arg
iif x,y,z "ternary operator", like CASE expression
nullif x,y returns X if x!=y, otherwise returns NULL

Math

  ARGS DESCRIPTION
abs n returns the absolute value,
max x ,y ,…  
min x ,y ,…  
random - pseudo-random integer
sign x return -1,0 or +1 for negative, zero or positive
exp x e^x
ln x natural logarithm
mod x,y remainder of x/y
pi -  
pow[er] x,y x^y
sqrt x  
degrees x radians -> degrees
radians x degrees -> radians
round x [,y] round float by y digits, default y=0
ceil[ing] x rounding
floor x rounding down
trunc x rounding

Date and Time

https://www.sqlite.org/lang_datefunc.html

  • no special type available
  • all functions, can take
    • no arguments to return the current time in FN format
    • an optional modifier
      • which can be used to modify the value red by adding/sub "2 days" in human language
      • or to affect how the value is interpreted, "unixepoch"
    returns..  
date tv, modifer… %Y-%m-%d  
time tv, modifer… %H:%M:%S  
datetime tv, modifer… %Y-%m-%d %H:%M:%S  
julianday tv, modifer… 2460396.3689133  
unixepoch tv, modifer… %s added on 3.38 (2022-02)
srtftime fmt, tv, modifer…    
timediff tv, tv   added on 3.43 (2023-08)
time-value (tv)
  • YYYY-MM-DD
  • YYYY-MM-DD HH:MM
  • YYYY-MM-DD HH:MM:SS (ISO-8601)
  • YYYY-MM-DD HH:MM:SS.SSS
  • YYYY-MM-DDTHH:MM
  • YYYY-MM-DDTHH:MM:SS
  • YYYY-MM-DDTHH:MM:SS.SSS
  • HH:MM
  • HH:MM:SS
  • HH:MM:SS.SSS
  • now
  • DDDDDDDDDD

BLOB

hex x blob -> string
unhex x[,y] ? -> blob
instr x,y  
length x length in bytes
octet_length x  
randomblob n n-byte blob
substr[ing] x,y  
zeroblob n n-bytes of 0x00

Aggregate

https://www.sqlite.org/lang_aggfunc.html

  args description
avg x interprets string/blob values as zero, floating point
count x number of times that x is not-null
  * total number of rows in a group
max x -
min x -
sum x -
decimal_sum x same as sum(), for floats sum, avoids imprecisions
total x same as sum(), but returns 0.0 if all values are null
group_concat x[,sep] "," is used if sep(arator) is ommited
string_agg x ,sep alias of group_concat(x,sep)

Foreign Keys

https://www.sqlite.org/foreignkeys.html

create table artist( -- parent table
  artistid   integer primary key, -- parent key
  artistname text
);
create table track( -- child table
  trackid     integer,
  trackname   text,
  trackartist integer, -- add NOT NULL? -- child key
  foreign key(trackartist) references artist(artistid)
);
create index trackindex ON track(trackartist); -- !!! not created automatically
  • Disabled by default
  • Enabled on each db connection

    > PRAGMA foreign_keys = ON; -- ON=1 OFF=0
    
  • Used to enforce "exists" relationships between tables
  • If foreign key is NULL, then no corresponding parent entry is required

FTS - Full Text Search

https://www.sqlite.org/fts5.html

create virtual table mytablename using fts5(
  linkid UNINDEXED, -- not added to the FTS index
  header, -- mostly ignores "column options", everything after the table name, but warns if type doesn't match
  title,
  columnsize=0 -- ?
);
select * from tb1
where col1 match ? AND col2 match ?;

changelog

https://www.sqlite.org/changes.html

23 3.44 CONCAT()
20 3.32 csv import
16 3.14 csv virtual table
15 3.37.1 strictly typed tables
15 3.8.11 FTS5
10 3.7.4 FTS4
09 3.6.19 foreign key constraints

extensions

tools

bindings

exercism

  • subselects or WITH RECURSIVE, do not well with UPDATE
  • iif() is a sweet ternary operator (sadly not available on postgresql)
  • there is a boolean (true/false) but internally is converted to 1/0, there is no type for it
  • there is mod(), but % is still an option
  • you have = and = for equality and have ! and <> for inequality
  • you can do 2 UPDATE passes
    • 1st pass to load intermediate results
    • 2nd pass to cleanup