Ошибки SQLite: коды, причины и решения

SQLite возвращает ошибки в виде числовых кодов и текстовых сообщений. Зная код и сообщение — легко понять причину и исправить. В этой статье разобраны все основные ошибки: от банальной no such table до повреждения файла базы данных.

Коды ошибок SQLite — справочник

Каждая ошибка SQLite имеет числовой код. Вот основные:

КодКонстантаОписание
0SQLITE_OKУспех, ошибок нет
1SQLITE_ERRORОбщая ошибка SQL (синтаксис, отсутствие таблицы/столбца)
5SQLITE_BUSYБаза заблокирована другим процессом
6SQLITE_LOCKEDТаблица заблокирована в текущем соединении
11SQLITE_CORRUPTФайл базы данных повреждён
14SQLITE_CANTOPENНе удаётся открыть файл базы данных
19SQLITE_CONSTRAINTНарушение ограничения: UNIQUE, FOREIGN KEY, NOT NULL
26SQLITE_NOTADBФайл не является базой данных SQLite

Получить код ошибки в Python: e.sqlite_errorcode (Python 3.11+) или через константы sqlite3.SQLITE_*.


Ошибка «no such table» (код 1)

Самая частая ошибка. Полное сообщение: OperationalError: no such table: имя_таблицы

Причины

  • Таблица не была создана — CREATE TABLE не выполнялась
  • Опечатка в имени таблицы
  • Подключение к другому файлу базы данных (не к тому где создана таблица)
  • Таблица создана в другой транзакции, которая не завершилась COMMIT

Как проверить список таблиц

-- Посмотреть все таблицы в базе
SELECT name FROM sqlite_master WHERE type = 'table';

-- Или через точечную команду в консоли sqlite3
.tables

Решение

-- Создать таблицу если её нет (без ошибки при повторном запуске)
CREATE TABLE IF NOT EXISTS users (
    id    INTEGER PRIMARY KEY,
    name  TEXT NOT NULL,
    email TEXT UNIQUE
);

В Python убедитесь что подключаетесь к правильному файлу и что CREATE TABLE выполняется до первого SELECT / INSERT:

import sqlite3

conn = sqlite3.connect('mydb.db')  # убедитесь что путь к нужному файлу
cursor = conn.cursor()

# Создаём таблицу если не существует
cursor.execute('''
    CREATE TABLE IF NOT EXISTS users (
        id    INTEGER PRIMARY KEY,
        name  TEXT NOT NULL
    )
''')
conn.commit()

Ошибка «no such column» (код 1)

Полное сообщение: OperationalError: no such column: имя_столбца

Причины и решение

-- Посмотреть структуру таблицы (какие столбцы есть)
PRAGMA table_info(users);
-- Результат: cid | name  | type    | notnull | dflt_value | pk

-- Ошибка: столбец phone не существует
SELECT phone FROM users;  -- OperationalError: no such column: phone

-- Решение: проверить имя или добавить столбец
ALTER TABLE users ADD COLUMN phone TEXT;

Ошибка «syntax error near…» (код 1)

Полное сообщение: OperationalError: near "X": syntax error

Частые причины

ОшибкаПричинаИсправление
near "WHERE": syntax errorЛишняя запятая или отсутствует FROMПроверить структуру SELECT
near ")": syntax errorЛишняя скобка или запятая перед )Убрать лишнюю запятую в последней строке CREATE TABLE
near "VALUES": syntax errorНеправильный синтаксис INSERTИспользовать INSERT INTO table VALUES (...)
near "=": syntax errorWHERE без пробелов или неверный операторПроверить условие

Типичные примеры

-- ❌ Лишняя запятая перед закрывающей скобкой
CREATE TABLE users (
    id   INTEGER PRIMARY KEY,
    name TEXT NOT NULL,     -- ← эта запятая вызывает "near ')': syntax error"
);

-- ✅ Правильно — без запятой после последнего поля
CREATE TABLE users (
    id   INTEGER PRIMARY KEY,
    name TEXT NOT NULL
);

-- ❌ Забыли INTO
INSERT users VALUES (1, 'Иван');  -- near "users": syntax error

-- ✅ Правильно
INSERT INTO users VALUES (1, 'Иван');

Ошибка «database is locked» (коды 5 и 6)

Полные сообщения: OperationalError: database is locked или database table is locked

SQLITE_BUSY (код 5) vs SQLITE_LOCKED (код 6)

КодСитуация
SQLITE_BUSY (5)Другой процесс удерживает блокировку на файл базы данных
SQLITE_LOCKED (6)Другой запрос в том же соединении удерживает блокировку таблицы

Причины и решения

import sqlite3

# Причина 1: незакрытая транзакция в другом соединении
# Решение: всегда закрывать соединения и делать commit/rollback

conn = sqlite3.connect('mydb.db')
conn.execute('BEGIN')
conn.execute("INSERT INTO users VALUES (1, 'Иван')")
# Забыли commit — следующее соединение получит "database is locked"
conn.commit()  # ← обязательно
conn.close()

# Причина 2: длительная транзакция
# Решение: установить timeout
conn = sqlite3.connect('mydb.db', timeout=10)  # ждать 10 секунд

# Причина 3: несколько потоков используют одно соединение
# Решение: каждый поток создаёт своё соединение
conn = sqlite3.connect('mydb.db', check_same_thread=False)
# Или лучше: создавать соединение внутри каждого потока

Настройка WAL-режима устраняет большинство блокировок при конкурентном чтении:

-- WAL позволяет читать во время записи
PRAGMA journal_mode = WAL;

Ошибка «unable to open database file» (код 14)

Полное сообщение: OperationalError: unable to open database file

Причины и решения

import sqlite3
import os

# Причина 1: неверный путь к файлу
conn = sqlite3.connect('/nonexistent/path/mydb.db')  # ошибка!

# Решение: проверить и создать директорию
db_path = '/path/to/data/mydb.db'
os.makedirs(os.path.dirname(db_path), exist_ok=True)
conn = sqlite3.connect(db_path)  # теперь создаст файл

# Причина 2: нет прав на запись в директорию
# Решение: проверить права
# ls -la /path/to/data/
# chmod 755 /path/to/data/

# Причина 3: диск заполнен
# df -h  — проверить свободное место

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


Ошибка UNIQUE constraint failed (код 19)

Полное сообщение: IntegrityError: UNIQUE constraint failed: users.email

Возникает при попытке вставить запись с уже существующим значением в поле с ограничением UNIQUE или PRIMARY KEY.

-- Таблица с уникальным email
CREATE TABLE users (
    id    INTEGER PRIMARY KEY,
    email TEXT UNIQUE
);

INSERT INTO users VALUES (1, 'ivan@example.com');
INSERT INTO users VALUES (2, 'ivan@example.com');
-- IntegrityError: UNIQUE constraint failed: users.email

Решения

-- Вариант 1: INSERT OR IGNORE — пропустить дубликат без ошибки
INSERT OR IGNORE INTO users VALUES (2, 'ivan@example.com');

-- Вариант 2: INSERT OR REPLACE — заменить существующую запись
INSERT OR REPLACE INTO users VALUES (2, 'ivan@example.com');

-- Вариант 3: INSERT OR UPDATE (upsert, SQLite 3.24+)
INSERT INTO users (id, email) VALUES (2, 'ivan@example.com')
ON CONFLICT(email) DO UPDATE SET id = excluded.id;
import sqlite3

conn = sqlite3.connect('mydb.db')
try:
    conn.execute("INSERT INTO users VALUES (2, 'ivan@example.com')")
    conn.commit()
except sqlite3.IntegrityError as e:
    print(f'Дубликат: {e}')  # UNIQUE constraint failed: users.email

Ошибка FOREIGN KEY constraint failed (код 19)

Полное сообщение: IntegrityError: FOREIGN KEY constraint failed

Важно: в SQLite внешние ключи выключены по умолчанию. Если ошибка не появляется — скорее всего PRAGMA foreign_keys не включён, и нарушения молча игнорируются.

-- Обязательно включать при каждом подключении
PRAGMA foreign_keys = ON;

-- Теперь это вызовет ошибку, если customer_id = 999 не существует в таблице customers:
INSERT INTO orders (customer_id, amount) VALUES (999, 150.00);
-- IntegrityError: FOREIGN KEY constraint failed

Диагностика

-- Проверить все нарушения внешних ключей в базе
PRAGMA foreign_key_check;

-- Проверить конкретную таблицу
PRAGMA foreign_key_check(orders);

Ошибка «database disk image is malformed» (код 11)

Полное сообщение: DatabaseError: database disk image is malformed

Файл базы данных повреждён. Причины: некорректное завершение записи, сбой диска, повреждение файловой системы.

Шаги восстановления

# Шаг 1: проверить целостность
sqlite3 mydb.db "PRAGMA integrity_check;"
# OK — база в порядке
# Список ошибок — есть повреждения

# Шаг 2: попытаться восстановить через dump
sqlite3 mydb.db ".recover" > recovered.sql
# Или старый способ:
sqlite3 mydb.db ".dump" > dump.sql

# Шаг 3: создать новую базу из дампа
sqlite3 new_mydb.db < recovered.sql
-- Шаг 4: пересобрать базу (помогает при лёгких повреждениях)
VACUUM;

Профилактика: включите WAL-режим и делайте резервные копии через SQLite Online Backup API — он гарантирует консистентное копирование без блокировок.


Как правильно обрабатывать ошибки SQLite в Python

Модуль sqlite3 в Python выбрасывает разные исключения в зависимости от типа ошибки:

Исключение PythonКогда возникает
sqlite3.OperationalErrorОшибки выполнения: no such table, database is locked, syntax error
sqlite3.IntegrityErrorНарушение ограничений: UNIQUE, FOREIGN KEY, NOT NULL, CHECK
sqlite3.DatabaseErrorПовреждение базы данных (malformed)
sqlite3.ProgrammingErrorОшибки программиста: закрытый курсор, неверный тип параметра
sqlite3.ErrorБазовый класс — перехватывает все ошибки SQLite
import sqlite3

def safe_insert(conn, user_id, email):
    try:
        conn.execute(
            "INSERT INTO users (id, email) VALUES (?, ?)",
            (user_id, email)
        )
        conn.commit()
        return True

    except sqlite3.IntegrityError as e:
        # UNIQUE constraint, FOREIGN KEY, NOT NULL
        print(f'Нарушение ограничения: {e}')
        conn.rollback()
        return False

    except sqlite3.OperationalError as e:
        # no such table, database is locked, syntax error
        print(f'Ошибка выполнения: {e}')
        conn.rollback()
        return False

    except sqlite3.DatabaseError as e:
        # повреждение базы
        print(f'Критическая ошибка базы данных: {e}')
        conn.rollback()
        return False

# Использование
conn = sqlite3.connect('mydb.db')
conn.execute("PRAGMA foreign_keys = ON")  # включить проверку FK
safe_insert(conn, 1, 'ivan@example.com')
conn.close()

Получить код ошибки (Python 3.11+)

try:
    conn.execute("SELECT * FROM nonexistent")
except sqlite3.OperationalError as e:
    print(e.sqlite_errorcode)   # 1 (SQLITE_ERROR)
    print(e.sqlite_errorname)   # 'SQLITE_ERROR'

Быстрая диагностика: что делать когда SQLite выдаёт ошибку

  1. Прочитайте полное сообщение — SQLite всегда указывает что именно не так: имя таблицы, столбца, позицию в запросе
  2. Проверьте таблицы и структуруSELECT name FROM sqlite_master WHERE type='table' и PRAGMA table_info(tablename)
  3. Проверьте целостность базыPRAGMA integrity_check
  4. Убедитесь что нет незакрытых транзакций — все BEGIN должны завершаться COMMIT или ROLLBACK
  5. Включите PRAGMA foreign_keys = ON — если работаете с внешними ключами

Читайте также

Оцените статью
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x