SQLite: small, self-contained SQL databases
Table of Contents
- Installation and first use
- Basic commands
- Meta commands and parameters
- Inline SQL statements
- More SQL functions
- Examples
SQLite is an open source C library that implements a fast, simple SQL database engine. Unlike other database engines, SQLite reads and writes directly to ordinary disk files.
Installation and first use
Just need to install sqlite3
package, available on most operating systems. To create (or open) a database, run:
sqlite3 <database file>
- Database files have the
.db
suffix (sqlite3 mydatabase.db
).
Basic commands
SQLite commands are very similar to those of other SQL engines. Check https://www.sqlite.org/docs.html for more info. These SQL commands need to end with a semicolon ;
.
Note: you can write multi-line commands by pressing Enter before typing the semicolon character. To cancel a command after pressing Enter, you can generate a deliberate syntax error (after closing any single or double-quote string). For example:
sqlite> select * from tavle1
...> ** error
...>;
Create table
create table mytable (id integer primary key, name text);
- When adding
primary key
to a column, that field will auto increment with each record (and will set the column value to ‘1’ in the first record). This is better than usingautoincrement
.
create table mytable (fecha text, lectura integer);
- There is no
date
format in SQLite, but you can use date and time functions to format dates.
Insert record
insert into mytable (name) values ("Ricardo");
- If you are going to type all column values, you don’t need to type the column name.
insert into mytable values (1, "Ricardo");
View records
select * from mytable;
- To view only specific columns, type the column names (separated by commas) instead of
*
. - use
where
to filter:
select * from mytable where name="Ricardo";
Filtering by dates (using date and time functions or string comparisons):
# selecting data before year 2022
sqlite> select * from mytable where strftime('%Y', fecha) < strftime('%Y', '2022-01-01');
2021-06-04|177
2021-08-10|184
sqlite> select * from lectura where fecha < '2022-01-01';
2021-06-04|177
2021-08-10|184
Adding units to results:
sqlite> .headers on
sqlite> select date, temp || ' ºC' as 'temp_in_celsius' from table1;
date|temp_in_celsius
2024-01-01|30 ºC
sqlite> select date, concat(col1, ' m3') as 'measurement' from table1;
Comparison operators
=
, ==
, <
, <=
, >
, >=
, !=
, IN
, NOT IN
, BETWEEN
, IS
, IS NOT
, ISNULL
, LIKE
, NOT LIKE
.
- Note: with
LIKE
,col1 LIKE '%word%'
will find ‘word’ and ‘WORD’ (case insensitive), butcol1 like '%patrón%'
will only find ‘patrón’, not ‘PATRÓN’ (case sensitive).
Math operators
+
, -
, *
, /
- Note: if you divide integer columns, you’ll get an integer value. To get a float number, first convert the integers to float (by multiplying them by
1.0
):select col1 * 1.0 / days from table1
.
Delete records
delete from mytable where id=1;
Delete table
drop table mytable;
Copy table
If you need to rearrange the columns or simply make a copy of an existing table (without previously exporting it to CSV):
Changing columns order:
create table table2 as select col1,col3,col2 from table1;
Without changing columns order:
create table copyTable as select * from table1;
Add column
alter table table1 add column new_column text;
Rename table
alter table table1 rename to table2;
Meta commands and parameters
Don’t add ;
when using sqlite meta commands.
Exit from sqlite
.quit
# or
.exit
- You can also press Ctrl+D.
Export to CSV
.mode csv
.headers on
.once data.csv
select * from mytable;
A simpler way, using sqlite command line parameters:
sqlite3 -csv -header mydatabase.db 'select * from mytable' > table.csv
- You can use single or double quotes for the query, but be careful when you use single quotes inside the query:
sqlite3 -csv -header mydatabase.db "select * from mytable where col1 like '%someword%'" > table.csv
List tables
.tables
Table info (schema)
.schema mytable
Show every table (and view) schema
.schema
Change table visualization
- Separate by columns:
.mode column
- Like a table:
.mode box
- Change column width:
.width <col1_width> <col2_width> ...
-
A value of ‘0’ means auto width, a negative value means right-justified.
-
Wrap text (to
<number>
characters):
.mode box --wrap <number>
- Valid for
box
andcolumn
modes. - Add
-ww
to wrap the text word by word, not by letters.
Import from CSV
.import --csv --skip 1 /path/to/file.csv mytable
--skip 1
will skip first row (for existing tables). Don’t include this parameter to import to a non-existent table.
Inline SQL statements
sqlite3 mydatabase.db 'select * from mytable'
More SQL functions
sum(col1)
: sum of values from ‘col1’.round(sum(col1), 2)
: round the previous sum to 2 decimals.col1 + col2
,col1 - col2
: when doing this kind of arithmetic operations, to ensure anull
value is treated as zero, you can use theiif
function (orcase
):
(iif("col1" ISNULL, 0, "col1") - iif("col2" ISNULL, 0, "col2"))
(case when "col1" ISNULL then 0 else "col1" end - case when "col2" ISNULL then 0 else "col2" end)
format('<PATTERN>', column)
: format a column value. Similar toprintf
.format('%.2f', col1)
: number with two decimals.format('%6.2f', col1)
: number with two decimals, padded to the right if it is less than six characters long (including the decimal separator: ‘123.45’).
printf('%6.2f', col1)
substr(column, <start>, <end>)
: returns a substring ofcolumn
, starting with the<start>
-th character, with<end>
characters long.<end>
can be omitted.
select substr(col1, 0, 5) as my_generated_column from table1;
Examples
- Calculating differences
sqlite> select * from table1;
date value
------------ -------
2021-06-04 177
2021-08-10 184
2021-10-07 190
2021-12-06 197
2022-02-04 203
2022-04-05 210
sqlite> CREATE VIEW table1_diff as select table1.date, (table1.value - t_next.value) as diff from table1 inner join table1 as t_next on l_next.rowid = table1.rowid - 1;
sqlite> select * from table1_diff;
date diff
------------ ----------
2021-08-10 7
2021-10-07 6
2021-12-06 7
2022-02-04 6
2022-04-05 7
- Calculating an account balance
sqlite> select * from balance;
date description income expense
---------- -------------- ------- -----
2024-01-01 Saldo anterior 150
2024-01-02 Ingreso1 200
2024-01-02 Gasto1 30
2024-01-02 Gasto2 22.5
sqlite> CREATE VIEW balance_total as select date, description, income, expense, round(iif(sum(income) over (order by rowid) ISNULL, 0, sum(income) over (order by rowid)) - iif(sum(expense) over (order by rowid) ISNULL, 0, sum(expense) over (order by rowid)), 2) as current_total from balance;
sqlite> select * from balance_total;
date description income expense current_total
---------- -------------- ------- ----- ------------
2024-01-01 Saldo anterior 150 150.0
2024-01-02 Ingreso1 200 350.0
2024-01-02 Gasto1 30 320.0
2024-01-02 Gasto2 22.5 297.5
- Find the deviation from average
sqlite> select col1 - (select avg(col1) from table1) as 'deviation_from_average' from table1;
- Search on several tables (with the same structure)
sqlite> select * from table1 where description like '%word%' union select * from table2 where description like '%otherword%' order by date;
- Formating numbers
sqlite> select * from table1;
┌────────────┬────────────────┬─────────┬───────┐
│ fecha │ concepto │ ingreso │ gasto │
├────────────┼────────────────┼─────────┼───────┤
│ 2024-01-01 │ Saldo anterior │ 150 │ │
│ 2024-01-02 │ Ingreso1 │ 200 │ │
│ 2024-01-02 │ Gasto1 │ │ 30 │
│ 2024-01-02 │ Gasto2 │ │ 22.5 │
│ 2024-01-04 │ Gasto3 │ │ 16.8 │
│ 2024-01-11 │ Gasto4 │ │ 5.52 │
└────────────┴────────────────┴─────────┴───────┘
sqlite> select fecha,concepto,iif(ingreso ISNULL, NULL, format('%9.2f',ingreso)) as ingreso, iif(gasto ISNULL,NULL,format('%9.2f',gasto)) as gasto from table1;
┌────────────┬────────────────┬───────────┬───────────┐
│ fecha │ concepto │ ingreso │ gasto │
├────────────┼────────────────┼───────────┼───────────┤
│ 2024-01-01 │ Saldo anterior │ 150.00 │ │
│ 2024-01-02 │ Ingreso1 │ 200.00 │ │
│ 2024-01-02 │ Gasto1 │ │ 30.00 │
│ 2024-01-02 │ Gasto2 │ │ 22.50 │
│ 2024-01-04 │ Gasto3 │ │ 16.80 │
│ 2024-01-11 │ Gasto4 │ │ 5.52 │
└────────────┴────────────────┴───────────┴───────────┘
- Calculate time between two dates on sucessive rows (as days) using
unixepoch()
(you can also usestrftime('%s', column)
)
sqlite> select (unixepoch(table1.date) - unixepoch(t1_next.date))/60/60/24 as days from table1 inner join table1 as t1_next on t1_next.rowid = table1.rowid - 1;
- Exclude results based on some criteria
select count(id) - (select count(id) from table1 where comments like '%word1%' or comments like '%word2%') as 'filteredResults' from table1;
- Group by first 5 characters of some column value:
select substr(description, 0, 5) as grouped_desc, sum(expenses) as sum_expenses from 2024 group by grouped_desc;
If you have any suggestion, feel free to contact me via social media or email.
Latest tutorials and articles:
Featured content: