1.3Kпросмотров
30.0%от подписчиков
10 февраля 2026 г.
Score: 1.5K
🔌 Python + SQLite: скрытые возможности (возврат изменённых строк, оконные функции) Все пишут SELECT и INSERT, но SQLite — это полноценная СУБД с фичами из больших баз. Используй RETURNING, UPSERT и оконные функции, чтобы логика работала на уровне данных, а не в коде. ⚡️ UPSERT: вставь или обнови одной командой Классика: нужно обновить запись, если она есть, иначе создать. Раньше требовалось два запроса. Теперь — один: import sqlite3 conn = sqlite3.connect(':memory:') conn.execute('''CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT UNIQUE, login_count INTEGER)''') # Первый вызов — вставит новую запись conn.execute('''INSERT INTO users (email, login_count) VALUES ('alice@mail.com', 1) ON CONFLICT(email) DO UPDATE SET login_count = login_count + 1''') # Второй вызов — увеличит счётчик conn.execute('''INSERT INTO users (email, login_count) VALUES ('alice@mail.com', 1) ON CONFLICT(email) DO UPDATE SET login_count = users.login_count + 1''') result = conn.execute('SELECT FROM users').fetchone() print(result) # (1, 'alice@mail.com', 2) ➡️ ON CONFLICT DO UPDATE — магия UPSERT. Ключевое поле должно иметь ограничение UNIQUE или PRIMARY KEY. ✅ RETURNING: возвращай изменённые строки сразу Раньше чтобы получить ID новой записи, делали отдельный SELECT. Теперь всё сразу: # Возвращаем ID и данные новой записи cursor = conn.execute('''INSERT INTO users (email, login_count) VALUES ('bob@mail.com', 1) RETURNING id, email''') new_user = cursor.fetchone() print(f'Новый ID: {new_user[0]}, email: {new_user[1]}') # Работает и с UPDATE/DELETE cursor = conn.execute('''UPDATE users SET login_count = login_count 2 WHERE email = 'alice@mail.com' RETURNING email, login_count''') updated = cursor.fetchone() print(f'Обновлено: {updated[0]}, новые логины: {updated[1]}') ➡️ RETURNING возвращает строки, затронутые INSERT, UPDATE или DELETE. Идеально для логирования и цепочек операций. 🧪 Оконные функции (OVER): аналитика без костылей Нужно пронумеровать строки, посчитать скользящее среднее или ранжировать — делай одним запросом: # Создадим таблицу с продажами conn.execute('''CREATE TABLE sales ( id INTEGER PRIMARY KEY, product TEXT, amount REAL, sale_date DATE )''') # Заполняем тестовыми данными sales_data = [ ('Ноутбук', 1000, '2024-01-15'), ('Ноутбук', 1200, '2024-01-20'), ('Мышь', 50, '2024-01-10'), ('Мышь', 45, '2024-01-18'), ('Клавиатура', 80, '2024-01-12'), ] conn.executemany('INSERT INTO sales (product, amount, sale_date) VALUES (?, ?, ?)', sales_data) # Ранжируем товары по убыванию суммы продаж внутри каждой категории cursor = conn.execute(''' SELECT product, amount, sale_date, ROW_NUMBER() OVER (PARTITION BY product ORDER BY amount DESC) as rank_in_product, SUM(amount) OVER (PARTITION BY product) as total_per_product, AVG(amount) OVER (ORDER BY sale_date ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) as moving_avg FROM sales ORDER BY product, amount DESC ''') for row in cursor.fetchall(): print(row) ➡️ OVER (PARTITION BY ... ORDER BY ...) создаёт "окно" для вычислений. Не путать с GROUP BY — здесь строки не сворачиваются. 🗣 Запомни: Современный SQLite — это не просто хранилище. Используй UPSERT для атомарных обновлений, RETURNING чтобы не делать лишних запросов, а оконные функции — для аналитики прямо в БД. Понра
1.3K
просмотров
4000
символов
Да
эмодзи
Нет
медиа

Другие посты @pytstart

Все посты канала →
🔌 Python + SQLite: скрытые возможности (возврат изменённых — @pytstart | PostSniper