SQLite автоинкремент и автоподстановка даты: пошаговое руководство

    При разработке бота для Telegram на Python с использованием SQLite часто возникает необходимость автоматически заполнять поля: идентификатор записи (автоинкремент) и текущую дату. В этой статье мы разберём типичную ошибку начинающих разработчиков и покажем правильный способ реализации.

    Почему возникает ошибка near "INTO": syntax error?

    Ошибка возникает из-за некорректного синтаксиса триггера SQLite. В SQLite нельзя использовать SELECT ... INTO для присвоения значения полю внутри триггера. Вместо этого применяется ключевое слово SET или NEW.поле = .... Кроме того, в вашем коде пропущена кавычка в списке значений для CHECK.

    Как правильно создать таблицу с автоинкрементом и датой

    Для автоматического увеличения log_id используйте INTEGER PRIMARY KEY AUTOINCREMENT. Для подстановки текущей даты при вставке записи примените триггер с корректным синтаксисом.

    Исправленный код таблицы

    CREATE TABLE data_matrix_logs (
        log_id INTEGER PRIMARY KEY AUTOINCREMENT,
        user_id INT,
        request_type TEXT,
        tp_code TEXT,
        requested_count INT,
        request_date TEXT,
        processing_status TEXT CHECK (processing_status IN ('Created', 'Revert', 'Complete')),
        FOREIGN KEY (user_id) REFERENCES users(user_id)
    );

    Правильный триггер для автоподстановки даты

    CREATE TRIGGER IF NOT EXISTS set_request_date_and_status
    BEFORE INSERT ON data_matrix_logs
    FOR EACH ROW
    BEGIN
        SET NEW.request_date = datetime('now');
        SET NEW.processing_status = 'Created';
    END;

    Альтернативный способ: DEFAULT значения

    Если вы не хотите использовать триггер, можно задать значения по умолчанию прямо в определении таблицы:

    CREATE TABLE data_matrix_logs (
        log_id INTEGER PRIMARY KEY AUTOINCREMENT,
        user_id INT,
        request_type TEXT,
        tp_code TEXT,
        requested_count INT,
        request_date TEXT DEFAULT (datetime('now')),
        processing_status TEXT DEFAULT 'Created' CHECK (processing_status IN ('Created', 'Revert', 'Complete')),
        FOREIGN KEY (user_id) REFERENCES users(user_id)
    );

    Этот способ проще и не требует создания отдельного триггера. При вставке записи без указания request_date и processing_status они будут заполнены автоматически.

    Полный исправленный код класса DB

    import sqlite3 as sq
    from conf_lib import Config
    
    class DB:
        def __init__(self):
            self.db_file = Config().get('DATABASE', 'db_file')
            self.connection = sq.connect(self.db_file)
        
        def build_db(self):
            cursor = self.connection.cursor()
            
            user_tables = '''
    CREATE TABLE IF NOT EXISTS users (
        user_id INT PRIMARY KEY,
        username VARCHAR(255),
        first_name VARCHAR(255),
        last_name VARCHAR(255),
        role TEXT DEFAULT 'user'
    );
    '''
            products_tables = '''
    CREATE TABLE IF NOT EXISTS products (
        plu VARCHAR(255) PRIMARY KEY,
        name VARCHAR(255),
        barcodes TEXT
    );
    '''
            data_matrix_logs_tables = '''
    CREATE TABLE IF NOT EXISTS data_matrix_logs (
        log_id INTEGER PRIMARY KEY AUTOINCREMENT,
        user_id INT,
        request_type TEXT,
        tp_code TEXT,
        requested_count INT,
        request_date TEXT DEFAULT (datetime('now')),
        processing_status TEXT DEFAULT 'Created' CHECK (processing_status IN ('Created', 'Revert', 'Complete')),
        FOREIGN KEY (user_id) REFERENCES users(user_id)
    );
    '''
            cursor.execute(user_tables)
            cursor.execute(products_tables)
            cursor.execute(data_matrix_logs_tables)
            self.connection.commit()
            cursor.close()
            self.connection.close()

    Частые ошибки при работе с SQLite в Telegram-ботах

    • Пропущенные кавычки в CHECK: всегда проверяйте синтаксис списка значений.
    • Неправильный синтаксис триггера: используйте SET NEW.поле = значение, а не SELECT INTO.
    • Отсутствие IF NOT EXISTS: добавляйте эту проверку, чтобы избежать ошибок при повторном запуске.
    • Закрытие соединения: всегда закрывайте курсор и соединение после выполнения операций.

    Заключение

    Теперь вы знаете, как правильно настроить автоинкремент и автоматическую подстановку текущей даты в SQLite. Используйте DEFAULT (datetime('now')) для простоты или триггер для более сложной логики. Эти методы помогут избежать ошибок и сделают код вашего Telegram-бота чище и надёжнее.

    Часто задаваемые вопросы