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-бота чище и надёжнее.