Интеграция Python с реляционными СУБД: от SQLite до PostgreSQL
Работа с SQL базами данных в Python
Как использовать встроенный модуль sqlite3 для работы с SQLite?
SQLite является встроенной реляционной базой данных, не требующей отдельного сервера. Модуль sqlite3 входит в стандартную библиотеку Python, поэтому для его использования не нужно устанавливать дополнительные пакеты. Это наиболее эффективное решение для небольших проектов, прототипов и тестирования.
import sqlite3
# Создание подключения к файлу базы данных
conn = sqlite3.connect('example.db')
cursor = conn.cursor()
# Создание таблицы
cursor.execute('''CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE)''')
# Вставка данных
cursor.execute("INSERT INTO users (name, email) VALUES (?, ?)", ("Alice", "alice@example.com"))
conn.commit()
# Выборка данных
cursor.execute("SELECT * FROM users")
rows = cursor.fetchall()
for row in rows:
print(row)
conn.close()база данных sql python (sql база данных в python)
Возможные проблемы и ошибки:
- Ошибка sqlite3.OperationalError: no such table возникает, если таблица не создана перед запросом. Проверяется порядок выполнения команд.
- Ошибка sqlite3.IntegrityError: UNIQUE constraint failed при попытке вставить дубликат уникального поля. Следует обрабатывать исключения с помощью try/except.
- Блокировка файла базы данных при параллельных записях. Для многопользовательских сценариев лучше использовать клиент-серверные СУБД.
Как подключиться к PostgreSQL через psycopg2?
Для работы с PostgreSQL требуется установка драйвера psycopg2 (или его версии psycopg2-binary). Вариант подходит для промышленных приложений, где необходимы транзакции, сложные запросы и масштабирование.
import psycopg2
conn = psycopg2.connect(
host="localhost",
database="testdb",
user="postgres",
password="secret"
)
cursor = conn.cursor()
# Создание таблицы
cursor.execute("""
CREATE TABLE IF NOT EXISTS employees (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
salary NUMERIC
)""")
# Вставка данных
cursor.execute("INSERT INTO employees (name, salary) VALUES (%s, %s)", ("Bob", 50000))
conn.commit()
# Чтение
cursor.execute("SELECT * FROM employees")
records = cursor.fetchall()
print(records)
conn.close()Распространенные ошибки:
- psycopg2.OperationalError: connection to server at ... failed - сервер PostgreSQL не запущен или параметры подключения неверны. Проверяется статус сервера.
- psycopg2.errors.UniqueViolation - нарушение уникальности. Используется обработка исключений с откатом транзакции (rollback).
- Утечка соединений: не забывать закрывать connection после работы или использовать контекстный менеджер with.
Как выполнять запросы к MySQL через pymysql?
Библиотека pymysql является чистым Python-драйвером для MySQL. Работа с ней аналогична psycopg2, но синтаксис плейсхолдеров отличается: используется %s.
import pymysql
conn = pymysql.connect(
host='localhost',
user='root',
password='password',
database='shop',
charset='utf8mb4'
)
cursor = conn.cursor()
# Создание таблицы
cursor.execute("""
CREATE TABLE IF NOT EXISTS products (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200),
price DECIMAL(10,2)
)""")
# Вставка
sql = "INSERT INTO products (title, price) VALUES (%s, %s)"
cursor.execute(sql, ('Laptop', 750.00))
conn.commit()
# Выборка
cursor.execute("SELECT * FROM products")
for row in cursor.fetchall():
print(row)
conn.close()Типичные трудности:
- pymysql.err.OperationalError: (1045, ...) - неверные учетные данные. Проверяется пользователь и пароль.
- pymysql.err.ProgrammingError: 1064 - синтаксическая ошибка SQL. Рекомендуется экранировать значения через плейсхолдеры, а не подставлять строки.
- Отсутствие обработки транзакций: по умолчанию autocommit выключен, требуется явно вызывать commit().
Как абстрагироваться от конкретной СУБД с помощью SQLAlchemy?
SQLAlchemy - это мощная ORM (Object-Relational Mapping) и SQL Toolkit, позволяющая работать с различными базами данных через единый интерфейс. Вариант подходит для больших проектов, где важна гибкость смены СУБД.
from sqlalchemy import create_engine, Column, Integer, String, Float
from sqlalchemy.orm import declarative_base, sessionmaker
# Определение модели
Base = declarative_base()
class Product(Base):
__tablename__ = 'products'
id = Column(Integer, primary_key=True)
name = Column(String(100))
price = Column(Float)
# Подключение (SQLite для примера)
engine = create_engine('sqlite:///store.db')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
# Добавление записи
new_product = Product(name='Keyboard', price=45.99)
session.add(new_product)
session.commit()
# Чтение
products = session.query(Product).all()
for p in products:
print(p.name, p.price)
session.close()Сложности при использовании SQLAlchemy:
- Необходимо правильно настраивать строку подключения (connection URI). Ошибка в URI приводит к sqlalchemy.exc.NoSuchModuleError.
- Производительность ORM может быть ниже прямых SQL-запросов из-за накладных расходов на отображение объектов. Для высоконагруженных операций рекомендуется использовать Core API.
- Конфликт между сессиями при конкурентном доступе - требуется управление изоляцией транзакций.
Расширенные примеры работы с SQL базами данных в Python
Как выполнять транзакции с контролем ошибок?
import sqlite3
def transfer_funds(from_id, to_id, amount):
conn = sqlite3.connect('finance.db')
try:
cursor = conn.cursor()
cursor.execute("BEGIN")
cursor.execute("UPDATE accounts SET balance = balance - ? WHERE id = ?", (amount, from_id))
cursor.execute("UPDATE accounts SET balance = balance + ? WHERE id = ?", (amount, to_id))
conn.commit()
print("Транзакция выполнена")
except sqlite3.Error as e:
conn.rollback()
print(f"Ошибка: транзакция откачена: {e}")
finally:
conn.close()Вызов transfer_funds(1, 2, 100) переведет 100 единиц, либо откатит изменения при ошибке.
Как выполнять массовую вставку (bulk insert) в PostgreSQL?
import psycopg2
from psycopg2.extras import execute_values
conn = psycopg2.connect("dbname=test user=postgres password=secret")
cursor = conn.cursor()
data = [('Alice', 55000), ('Bob', 48000), ('Charlie', 62000)]
# execute_values - эффективная вставка многих строк
sql = "INSERT INTO employees (name, salary) VALUES %s"
execute_values(cursor, sql, data)
conn.commit()
cursor.execute("SELECT COUNT(*) FROM employees")
print(cursor.fetchone()[0]) # выведет 3
conn.close()Результат: 3 записи добавлены одной операцией.
Как использовать пул соединений для повышения производительности?
from sqlalchemy import create_engine
from sqlalchemy.pool import QueuePool
# Создание движка с пулом (по умолчанию QueuePool)
engine = create_engine(
'postgresql://user:pass@localhost/mydb',
poolclass=QueuePool,
pool_size=5,
max_overflow=10
)
# Использование в нескольких потоках
with engine.connect() as conn:
result = conn.execute("SELECT version()")
print(result.fetchone())Вывод: ('PostgreSQL 15.x on x86_64-pc-linux-gnu',)Как загрузить результаты SQL-запроса в Pandas DataFrame?
import pandas as pd
import sqlite3
conn = sqlite3.connect('example.db')
df = pd.read_sql_query("SELECT * FROM users", conn)
print(df.head())
conn.close()id name email 0 1 Alice alice@example.com
Как использовать raw SQL с SQLAlchemy Core без ORM?
from sqlalchemy import create_engine, text
engine = create_engine('sqlite:///test.db')
with engine.connect() as conn:
# Параметризованный запрос
result = conn.execute(text("SELECT * FROM products WHERE price > :min_price"), {"min_price": 100})
for row in result:
print(row)Вывод: (2, 'Laptop', 750.0) и другие строки с ценой более 100.
Как асинхронно работать с базой данных через aiosqlite?
import asyncio
import aiosqlite
async def main():
async with aiosqlite.connect('async.db') as db:
await db.execute('CREATE TABLE IF NOT EXISTS tasks (id INTEGER PRIMARY KEY, description TEXT)')
await db.execute('INSERT INTO tasks (description) VALUES (?)', ('Finish report',))
await db.commit()
async with db.execute('SELECT * FROM tasks') as cursor:
async for row in cursor:
print(row)
asyncio.run(main())Вывод: (1, 'Finish report')