SQLite3: встраиваемая SQL база данных

SQLite — это СУБД, которая работает внутри вашей программы как библиотека: нет сервера, который нужно запускать, нет пользователей и настроек. Вся база данных — таблицы, индексы и данные — это один обычный файл. sqlite3 — это третья версия формата этого файла и имя его оболочки командной строки.

На этой странице мы работаем с оболочкой, а потом открываем ту же базу из двух языков программирования. Если вы пишете на Python, статья SQLite3 Python шаг за шагом показывает модуль Python. Проверено в Ubuntu 24.04.5 LTS с sqlite3 3.45.1, Python 3 и PHP 8.2.

Что такое SQLite

Поэтому SQLite — обычный выбор для данных, которые принадлежат одной программе: браузеры и мобильные приложения хранят в ней настройки и историю, настольные программы — документы, тесты — временные данные, небольшие сайты — содержимое.

Установка оболочки sqlite3

sudo apt install sqlite3

sqlite3 --version

3.45.1 2024-01-30 16:01:20 e876e51a0ed5c5b3126f52e532044363a014bc594cfefa87ffb5b82257ccalt1 (64-bit)

Пакет содержит только оболочку. Программы используют библиотеку SQLite, которую большинство языков поставляют вместе с драйвером базы, поэтому программе оболочка не нужна.

Создать базу и таблицу

sqlite3 создаёт файл базы при первой записи. SQL после имени файла выполняется сразу:

sqlite3 shop.db "CREATE TABLE items (id INTEGER PRIMARY KEY, name TEXT NOT NULL, price REAL);"

sqlite3 shop.db "INSERT INTO items (name, price) VALUES ('Keyboard', 49.9), ('Mouse', 19.5), ('Monitor', 189);"

Столбец, объявленный как INTEGER PRIMARY KEY, нумерует строки сам. База — небольшой файл:

ls -l shop.db

-rw-r--r-- 1 andrei andrei 8192 Nov 2 23:28 shop.db

Без SQL после имени файла sqlite3 shop.db открывает интерактивную оболочку с приглашением sqlite>. Вводите SQL с точкой с запятой в конце, а для выхода — .quit.

Запросы и форматы вывода

sqlite3 shop.db 'SELECT * FROM items;'

1|Keyboard|49.9 2|Mouse|19.5 3|Monitor|189.0

По умолчанию столбцы разделены символом |. -header -column добавляет названия и выравнивает столбцы:

sqlite3 -header -column shop.db 'SELECT * FROM items;'

id name price -- -------- ----- 1 Keyboard 49.9 2 Mouse 19.5 3 Monitor 189.0

-box рисует таблицу:

sqlite3 -box shop.db 'SELECT name, price FROM items WHERE price < 100;'

┌──────────┬───────┐ │ name │ price │ ├──────────┼───────┤ │ Keyboard │ 49.9 │ │ Mouse │ 19.5 │ └──────────┴───────┘

а -json выводит строки для скриптов:

sqlite3 -json shop.db 'SELECT name, price FROM items WHERE price > 50;'

[{"name":"Monitor","price":189.0}, {"name":"Webcam","price":59.8999999999999985}]

Этот вывод получен в конце страницы, после того как импорт CSV добавил веб-камеру. 59.9 превращается в 59.8999999999999985, потому что REAL — двоичное число с плавающей точкой: оно хранит ближайшее двоичное значение, а вывод JSON и .dump печатают все его цифры. Денежные суммы храните в копейках в столбце INTEGER.

Таблицы и схема

sqlite3 shop.db .tables

items

sqlite3 shop.db '.schema items'

CREATE TABLE items (id INTEGER PRIMARY KEY, name TEXT NOT NULL, price REAL);

Команды, которые начинаются с точки, относятся к оболочке, а не к SQL. В интерактивной оболочке они работают так же, а .help показывает их все.

Импорт и экспорт CSV

Два новых товара пришли в CSV-файле со строкой заголовков:

cat new_items.csv

name,price Headset,35 Webcam,59.9

Импортируйте его в новую таблицу. Названия столбцов sqlite3 берёт из первой строки:

sqlite3 shop.db '.import --csv new_items.csv staging'

sqlite3 shop.db '.schema staging'

CREATE TABLE IF NOT EXISTS "staging"( "name" TEXT, "price" TEXT);

Все столбцы импортированной таблицы имеют тип TEXT. Скопируйте строки в настоящую таблицу, где они получат свои типы и id, и удалите промежуточную таблицу:

sqlite3 shop.db 'INSERT INTO items (name, price) SELECT name, price FROM staging; DROP TABLE staging;'

sqlite3 -header -column shop.db 'SELECT * FROM items;'

id name price -- -------- ----- 1 Keyboard 49.9 2 Mouse 19.5 3 Monitor 189.0 4 Headset 35.0 5 Webcam 59.9

Две ловушки прямого импорта: в файле два столбца, а в items три, а с --skip 1 в ещё не существующую таблицу sqlite3 пропускает заголовок и берёт названия столбцов из первой строки данных.

Экспорт работает в обратную сторону:

sqlite3 -csv -header shop.db 'SELECT * FROM items;' > items.csv

cat items.csv

id,name,price 1,Keyboard,49.9 2,Mouse,19.5 3,Monitor,189.0 4,Headset,35.0 5,Webcam,59.9

Дамп, восстановление и резервная копия

.dump записывает всю базу в виде SQL:

sqlite3 shop.db .dump > shop.sql

cat shop.sql

PRAGMA foreign_keys=OFF; BEGIN TRANSACTION; CREATE TABLE items (id INTEGER PRIMARY KEY, name TEXT NOT NULL, price REAL); INSERT INTO items VALUES(1,'Keyboard',49.8999999999999985); INSERT INTO items VALUES(2,'Mouse',19.5); INSERT INTO items VALUES(3,'Monitor',189.0); INSERT INTO items VALUES(4,'Headset',35.0); INSERT INTO items VALUES(5,'Webcam',59.8999999999999985); COMMIT;

Передайте его sqlite3, чтобы собрать из него новую базу:

sqlite3 restored.db < shop.sql

sqlite3 restored.db 'SELECT count(*) FROM items;'

5

.backup безопасно копирует базу, даже пока ею пользуется другая программа; обычный cp безопасен, только если в файл никто не пишет. Проверьте копию:

sqlite3 shop.db ".backup 'shop-backup.db'"

sqlite3 shop-backup.db 'PRAGMA integrity_check;'

ok

SQLite из языков программирования

Любой язык с драйвером SQLite открывает тот же файл. Обе программы ниже читают shop.db из шагов выше и выводят товары дешевле 50.

Python: модуль sqlite3 входит в стандартную библиотеку.

vi read_items.py

import sqlite3 con = sqlite3.connect("shop.db") for name, price in con.execute("SELECT name, price FROM items WHERE price < ?", (50,)): print(name, price) con.close()

python3 read_items.py

Keyboard 49.9 Mouse 19.5 Headset 35.0

PHP: PDO с расширением pdo_sqlite.

vi read_items.php

<?php $db = new PDO('sqlite:shop.db'); $query = $db->prepare('SELECT name, price FROM items WHERE price < ?'); $query->execute([50]); foreach ($query as $row) { echo $row['name'], ' ', $row['price'], PHP_EOL; }

php read_items.php

Keyboard 49.9 Mouse 19.5 Headset 35

Строки те же, с одним отличием: PHP печатает число 35.0 как 35. Другие языки используют такие драйверы (на этой странице не проверялись):

ЯзыкДрайвер
Cсама библиотека SQLite, заголовок sqlite3.h
JavaJDBC-драйвер org.xerial:sqlite-jdbc
Godatabase/sql с modernc.org/sqlite или github.com/mattn/go-sqlite3
Node.jsвстроенный node:sqlite начиная с Node 22.5 или better-sqlite3
Rustrusqlite
C#Microsoft.Data.Sqlite

Когда нужна серверная СУБД

Тогда используйте СУБД с сервером, например PostgreSQL или MySQL.

Автор статьи: Клавдия Кондакова