Опишите опыт работы с SQLAlchemy Core.

Ответ

SQLAlchemy Core — это низкоуровневая часть библиотеки SQLAlchemy, предоставляющая мощный и гибкий инструментарий для работы с SQL, в отличие от ORM. Она позволяет строить SQL-запросы программно, сохраняя полный контроль над генерируемым SQL.

Основные преимущества и сценарии использования:

  • Полный контроль над SQL: Позволяет писать запросы, максимально приближенные к "сырому" SQL, но с использованием Python-синтаксиса.
  • Высокая производительность: Отсутствие ORM-накладных расходов делает Core идеальным для высоконагруженных операций и сложных запросов, требующих тонкой оптимизации.
  • Гибкость: Удобен для работы с существующими базами данных, сложными схемами или когда ORM-моделирование избыточно.
  • Миграции и утилиты: Часто используется для написания миграций баз данных или служебных скриптов.

Пример использования SQLAlchemy Core:

from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, select

# Инициализация движка базы данных (SQLite in-memory)
engine = create_engine('sqlite:///:memory:')
metadata = MetaData()

# Определение таблицы
users = Table(
    'users', metadata,
    Column('id', Integer, primary_key=True),
    Column('name', String),
)

# Создание таблицы в базе данных
metadata.create_all(engine)

# Вставка данных
with engine.connect() as conn:
    conn.execute(users.insert(), [{'name': 'Alice'}, {'name': 'Bob'}])
    conn.commit() # Важно для сохранения изменений

# Выборка данных
query = select(users).where(users.c.name == 'Alice')
with engine.connect() as conn:
    result = conn.execute(query).fetchall()
    print(result) # Вывод: [(1, 'Alice')]

Я использую SQLAlchemy Core для реализации сложных запросов, требующих максимальной производительности, а также в случаях, когда ORM-абстракция является избыточной или ограничивающей.

Ответ 18+ 🔞

Ага, слушай, вот есть у нас эта SQLAlchemy, да? И все только и говорят про её ORM, про эти модели, сессии, отношения — ну, в общем, полный цирк с конями для лёгких задач. А знаешь, что там под капотом-то сидит, на чём вся эта махина едет? Правильно, SQLAlchemy Core, ёпта!

Это как если бы ORM был навороченным автопилотом в тачке, который сам рулит и переключает передачи, а Core — это ручное управление, где ты сам дергаешь за рычаги и давишь на педали. Хочешь выжать из базы всё, до последней капли производительности? Хочешь написать запрос такой изощрённый, что сам SQL-сервер ахуеет? Тогда тебе сюда.

Ну и нахуя оно надо, спросишь?

  • Контроль на уровне бога: Ты пишешь SQL, но не строками, а через питонячие объекты. Получается и мощно, и без риска опечататься в каком-нибудь WHEREE. SQL генерируется идеальный, именно такой, какой ты задумал.
  • Скорость, блядь: ORM — это круто, но он иногда такую обёртку накрутит, что запрос начинает по полчаса думать. Core снимает все эти накладные расходы. Чистый, злой SQL прямо в базу. Для аналитики, для массовых обновлений — просто песня.
  • Гибкость до одури: Работаешь с легаси-базой, где схема кривее горбатого забора? Или тебе просто надо быстро накидать скрипт для миграции? ORM будет плакать и кусать локти, а Core — как дома.
  • Инструменты для взрослых: Все эти утилиты для создания таблиц, миграции (Alembic, кстати, на нём же и работает) — под капотом у них Core.

Смотри, как это выглядит на практике, без всей этой ORM-мишуры:

from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, select

# Подключаем движок. Здесь in-memory SQLite, для примера.
engine = create_engine('sqlite:///:memory:')
metadata = MetaData()  # Это типа наша папка с чертежами всех таблиц

# Рисуем чертёж таблицы. Никаких классов-моделей, просто объявляем, что есть что.
users = Table(
    'users', metadata,
    Column('id', Integer, primary_key=True),
    Column('name', String),
)

# Берём чертёж и строим по нему таблицу в базе. Раз — и готово.
metadata.create_all(engine)

# Втыкаем данные. Видишь, как просто? Список словарей и execute.
with engine.connect() as conn:
    conn.execute(users.insert(), [{'name': 'Alice'}, {'name': 'Bob'}])
    conn.commit()  # А вот это, сука, не забывай! Иначе всё к хуям собачьим пропадёт.

# А теперь вытаскиваем обратно. Строим запрос через select().
query = select(users).where(users.c.name == 'Alice')  # `users.c` — это доступ к колонкам
with engine.connect() as conn:
    result = conn.execute(query).fetchall()
    print(result) # Смотри-ка: [(1, 'Alice')]

Вот и вся магия. Я сам к Core прибегаю, когда нужно либо выжать производительность до скрипа, либо когда запрос такой ебучно сложный, что через ORM его только наизнанку вывернуть. А для простых CRUD-операций, конечно, ORM — самое то. Но знать, что у тебя в арсенале есть такой лом — это, блядь, спокойствие на душе.