Here's why SQLite is perfect for your day-to-day work. It doesn't matter if you are a developer, analyst, tester, admin or product manager.
For starters, a few known facts:
SQLite is the most widely used database management system in the world and is included in all popular operating systems.
Works without a server.
For developers, it is embedded directly into the application.
For everyone else - a convenient console (REPL) in one file (sqlite3.exe on Windows, sqlite3 on Linux / macOS).
Console, import and export
The console is a killer feature of SQLite: a more powerful data analysis tool than Excel, and much simpler than any pandas. Data from CSV is loaded with one command, the table is created automatically:
> .import --csv city.csv city
> select count(*) from city;
1117
Basic SQL features are supported, and the console shows the result in a nice table. There are also advanced SQL features, but more about them later.
select
century || '- ' as dates,
count(*) as city_count
from history
group by century
order by century desc;
โโโโโโโโโโโโฌโโโโโโโโโโโโโ
โ dates โ city_count โ
โโโโโโโโโโโโผโโโโโโโโโโโโโค
โ 21- โ 1 โ
โ 20- โ 263 โ
โ 19- โ 189 โ
โ 18- โ 191 โ
โ 17- โ 137 โ
โ 16- โ 79 โ
โ 15- โ 39 โ
โ 14- โ 38 โ
โ 13- โ 27 โ
โ 12- โ 44 โ
โ 11- โ 8 โ
โ 10- โ 6 โ
โ 9- โ 4 โ
โ 5- โ 1 โ
โ 3- โ 1 โ
โโโโโโโโโโโโดโโโโโโโโโโโโโ
A bunch of data export formats: sql, csv, json, even markdown and html. Everything is done with a couple of commands:
.mode json
.output city.json
select city, foundation_year, timezone from city limit 10;
.shell cat city.json
[{"city":"","foundation_year":1969,"timezone":"UTC+3"},
{"city":"","foundation_year":1857,"timezone":"UTC+3"},
{"city":"-","foundation_year":1830,"timezone":"UTC+7"},
{"city":"","foundation_year":1913,"timezone":"UTC+7"},
{"city":"","foundation_year":1730,"timezone":"UTC+7"},
{"city":"","foundation_year":1846,"timezone":"UTC+7"},
{"city":"","foundation_year":1709,"timezone":"UTC+7"},
{"city":"","foundation_year":1942,"timezone":"UTC+7"},
{"city":"","foundation_year":1748,"timezone":"UTC+7"},
{"city":"","foundation_year":1736,"timezone":"UTC+7"}]
Working with JSON native
There is nothing more convenient than SQLite for parsing and transforming JSON. You can select data directly from the file, as if it were a regular table. Or load it into a table and select from there - as you prefer.
select
json_extract(value, '$.code') as code,
json_extract(value, '$.name') as name,
json_extract(value, '$.rate') as rate,
json_extract(value, '$.default') as "default"
from
json_each(readfile('currency.sample.json'))
;
โโโโโโโโฌโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโฌโโโโโโโโโโ โ code โ name โ rate โ default โ โโโโโโโโผโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโผโโโโโโโโโโค โ AZN โ โ 0.023107 โ 0 โ โ BYR โ โ 0.034966 โ 0 โ โ EUR โ โ 0.011138 โ 0 โ โ GEL โ โ 0.0344 โ 0 โ โ KGS โ โ 1.131738 โ 0 โ โ KZT โ โ 5.699857 โ 0 โ โ RUR โ โ 1.0 โ 1 โ โ UAH โ โ 0.380539 โ 0 โ โ USD โ โ 0.013601 โ 0 โ โ UZS โ โ 142.441417 โ 0 โ โโโโโโโโดโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโดโโโโโโโโโโ
It doesn't matter how sprawling the JSON is, you can choose the attributes of any nesting:
select
json_extract(value, '$.id') as id,
json_extract(value, '$.name') as name
from
json_tree(readfile('industry.sample.json'))
where
path like '$[%].industries'
;
โโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโ โ id โ name โ โโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโค โ 7.538 โ - โ โ 7.539 โ - โ โ 7.540 โ โ โ 9.399 โ โ โ 9.400 โ โ โ 9.401 โ โ โ 43.641 โ โ โ 43.646 โ โ โ 43.647 โ โ โโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโ
CTE and set operations
, Common Table Expressions ( WITH
) , . ( parent_id
) โ WITH
. ยซยป .
with recursive tmp(id, name, level) as (
select id, name, 1 as level
from area
where parent_id is null
union all
select
area.id,
tmp.name || ', ' || area.name as name,
tmp.level + 1 as level
from area
join tmp on area.parent_id = tmp.id
)
select * from tmp;
โโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโ โ id โ name โ level โ โโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโค โ 113 โ โ 1 โ โ 1 โ , โ 2 โ โ 1586 โ , โ 2 โ โ 1588 โ , , โ 3 โ โ 78 โ , , โ 3 โ โ 212 โ , , โ 3 โ โ ... โ ... โ ... โ โโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโ
? : UNION
, INTERSECT
, EXCEPT
.
select employer_id
from employer_area
where area_id = 1
except
select employer_id
from employer_area
where area_id = 2;
? โ :
alter table vacancy
add column salary_net integer as (
case when salary_gross = true then
round(salary_from/1.13)
else
salary_from
end
);
, :
select
substr(name, 1, 40) as name,
salary_net
from vacancy
where
salary_currency = 'RUR'
and salary_net is not null
limit 10;
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโ
โ name โ salary_net โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโค
โ - (Delphi) โ 40000 โ
โ Scala / Java ( Senio โ 60000 โ
โ Java / Kotlin Developer โ 150000 โ
โ 1 โ 150000 โ
โ C# โ 53097 โ
โ 1 โ 80000 โ
โ Java - (Middle, Senior) โ 100000 โ
โ C#/ .NET โ 70796 โ
โ / QA engineer ( โ 45000 โ
โ โ 17699 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโ
.
? : , , , . , . , ( ).
.load sqlite3-stats select count(*) as book_count, cast(avg(num_pages) as integer) as mean, cast(median(num_pages) as integer) as median, mode(num_pages) as mode, percentile_90(num_pages) as p90, percentile_95(num_pages) as p95, percentile_99(num_pages) as p99 from books;
โโโโโโโโโโโโโโฌโโโโโโโฌโโโโโโโโโฌโโโโโโโฌโโโโโโฌโโโโโโฌโโโโโโโ
โ book_count โ mean โ median โ mode โ p90 โ p95 โ p99 โ
โโโโโโโโโโโโโโผโโโโโโโผโโโโโโโโโผโโโโโโโผโโโโโโผโโโโโโผโโโโโโโค
โ 1483 โ 349 โ 295 โ 256 โ 640 โ 817 โ 1199 โ
โโโโโโโโโโโโโโดโโโโโโโดโโโโโโโโโดโโโโโโโดโโโโโโดโโโโโโดโโโโโโโ
. SQLite - . , โ . .
, . , :
. . , :
with slots as (
select
num_pages/100 as slot,
count(*) as book_count
from books
group by slot
),
max as (
select max(book_count) as value
from slots
)
select
slot,
book_count,
printf('%.' || (book_count * 30 / max.value) || 'c', '*') as bar
from slots, max
order by slot;
โโโโโโโโฌโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ slot โ book_count โ bar โ
โโโโโโโโผโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 0 โ 116 โ ********* โ
โ 1 โ 254 โ ******************** โ
โ 2 โ 376 โ ****************************** โ
โ 3 โ 285 โ ********************** โ
โ 4 โ 184 โ ************** โ
โ 5 โ 90 โ ******* โ
โ 6 โ 54 โ **** โ
โ 7 โ 41 โ *** โ
โ 8 โ 31 โ ** โ
โ 9 โ 15 โ * โ
โ 10 โ 11 โ * โ
โ 11 โ 12 โ * โ
โ 12 โ 2 โ * โ
โ 13 โ 5 โ * โ
โ 14 โ 3 โ * โ
โ 15 โ 1 โ * โ
โ 17 โ 1 โ * โ
โ 18 โ 2 โ * โ
โโโโโโโโดโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
SQLite ( โ ). INSERT
240 . CSV ( ) โ 2 .
.load sqlite3-vsv create virtual table temp.blocks_csv using vsv( filename="ipblocks.csv", schema="create table x(network text, geoname_id integer, registered_country_geoname_id integer, represented_country_geoname_id integer, is_anonymous_proxy integer, is_satellite_provider integer, postal_code text, latitude real, longitude real, accuracy_radius integer)", columns=10, header=on, nulls=on );
.timer on
insert into blocks
select * from blocks_csv;
Run Time: real 5.176 user 4.716420 sys 0.403866
select count(*) from blocks;
3386629
Run Time: real 0.095 user 0.021972 sys 0.063716
, SQLite , . . write-ahead log ( ) . โ , .
SQLite . , sqlite.org SQLite , (~200 ). 700 , 95% .
,
, ยซยป . .
SQLite : json json_extract()
:
create table currency(
body text,
code text as (json_extract(body, '$.code')),
name text as (json_extract(body, '$.name'))
);
create index currency_code_idx on currency(code);
insert into currency
select value
from json_each(readfile('currency.sample.json'));
explain query plan
select name from currency where code = 'RUR';
QUERY PLAN
`--SEARCH TABLE currency USING INDEX currency_code_idx (code=?)
. WITH RECURSIVE
, :
:
create virtual table books_fts
using fts5(title, author, publisher);
insert into books_fts
select title, author, publisher from books;
select
author,
substr(title, 1, 30) as title,
substr(publisher, 1, 10) as publisher
from books_fts
where books_fts match 'ann'
limit 5;
โโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโ โ author โ title โ publisher โ โโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโค โ Ruby Ann Boxcar โ Ruby Ann's Down Home Trailer P โ Citadel โ โ Ruby Ann Boxcar โ Ruby Ann's Down Home Trailer P โ Citadel โ โ Lynne Ann DeSpelder โ The Last Dance: Encountering D โ McGraw-Hil โ โ Daniel Defoe โ Robinson Crusoe โ Ann Arbor โ โ Ann Thwaite โ Waiting for the Party: The Lif โ David R. G โ โโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโ
in-memory ? :
db = sqlite3.connect(":memory:")
:
db = sqlite3.connect("file::memory:?cache=shared")
( PostgreSQL). UPSERT
, UPDATE FROM
generate_series()
. R-Tree . , fuzzy- . SQLite ยซยป .
, SQLite . , !
, SQLite โ @sqliter