Ответ 1
Однострочный обзор:
Поведение execute()
во всех случаях одинаково, но это три разных метода в классах Engine
, Connection
и Session
.
Что именно является execute()
:
Чтобы понять поведение execute()
нам нужно изучить класс Executable
. Executable
является суперклассом для всех типов "операторов", в том числе select(), delete(), update(), insert(), text() - в простейших словах, Executable
является конструкцией выражения SQL, поддерживаемой в SQLAlchemy.
Во всех случаях метод execute()
принимает текст SQL или построенное выражение SQL, то есть любое из множества конструкций выражений SQL, поддерживаемых в SQLAlchemy, и возвращает результаты запроса (ResultProxy
- ResultProxy
объект курсора DB-API
для обеспечения более легкого доступа к строке столбцы.)
Прояснить это дальше (только для концептуальных разъяснений, а не для рекомендуемого подхода):
В дополнение к Engine.execute()
(выполнение без установления соединения), Connection.execute()
и Session.execute()
, также можно использовать execute()
непосредственно в любой Executable
конструкции. Класс Executable
имеет собственную реализацию execute()
- согласно официальной документации, одно описание строки о том, что делает execute()
, это " Скомпилировать и выполнить эту Executable
". В этом случае нам нужно явно привязать Executable
(конструкцию выражения SQL) с объектом Connection
или объектом Engine
(который неявно получает объект Connection
), поэтому execute()
будет знать, где выполнить SQL
.
Следующий пример демонстрирует это хорошо - учитывая таблицу, как показано ниже:
from sqlalchemy import MetaData, Table, Column, Integer
meta = MetaData()
users_table = Table('users', meta,
Column('id', Integer, primary_key=True),
Column('name', String(50)))
Явное выполнение, т. Е. Connection.execute()
- передача текста SQL или построенное выражение SQL для метода execute()
Connection
:
engine = create_engine('sqlite:///file.db')
connection = engine.connect()
result = connection.execute(users_table.select())
for row in result:
# ....
connection.close()
Явное выполнение без установления соединения ie Engine.execute()
- передача текста SQL или построенное выражение SQL непосредственно к методу execute()
Engine:
engine = create_engine('sqlite:///file.db')
result = engine.execute(users_table.select())
for row in result:
# ....
result.close()
Неявное выполнение, т.е. Executable.execute()
также не требует установления соединения и вызывает метод execute()
Executable
, то есть он вызывает метод execute()
непосредственно в конструкции выражения SQL
(экземпляр Executable
).
engine = create_engine('sqlite:///file.db')
meta.bind = engine
result = users_table.select().execute()
for row in result:
# ....
result.close()
Примечание. Указанный пример неявного исполнения с целью уточнения - этот способ выполнения настоятельно не рекомендуется - согласно документам:
"неявное исполнение" - очень старый шаблон использования, который в большинстве случаев более запутан, чем полезен, и его использование не рекомендуется. Обе модели, по-видимому, способствуют чрезмерному использованию "коротких сокращений" в дизайне приложений, которые впоследствии приводят к проблемам.
Ваши вопросы:
Насколько я понимаю, если кто-то использует engine.execute, он создает соединение, открывает сеанс (Alchemy заботится об этом для вас) и выполняет запрос.
Вы правы для части "если кто-то использует engine.execute
он создает connection
", но не для "открывает session
(Alchemy заботится об этом для вас) и выполняет запрос" - использование Engine.execute()
и Connection.execute()
(почти) одно и то же, в формальном, объект Connection
создается неявно, а в более позднем случае мы явно его создаем. Что действительно происходит в этом случае:
'Engine' object (instantiated via 'create_engine()') -> 'Connection' object (instantiated via 'engine_instance.connect()') -> 'connection.execute({*SQL expression*})'
Но существует ли глобальная разница между этими тремя способами выполнения такой задачи?
На уровне БД это точно то же самое, все они выполняют SQL (текстовое выражение или различные конструкции выражения SQL). С точки зрения приложения есть два варианта:
- Прямое выполнение - использование
Engine.execute()
илиConnection.execute()
- Использование
sessions
- эффективно обрабатывает транзакцию как единую единицу работы, с легкостью черезsession.add()
,session.rollback()
,session.commit()
,session.close()
. Это способ взаимодействия с БД в случае ORM, т.е. сопоставленных таблиц. Предоставляет identity_map для мгновенного получения уже доступных или вновь созданных/добавленных объектов в течение одного запроса.
Session.execute()
конечном итоге использует метод выполнения инструкции Connection.execute()
для выполнения инструкции SQL. Использование объекта Session
- это метод SQLAlchemy ORM, рекомендованный для взаимодействия приложения с базой данных.
Выдержка из документов:
Важно отметить, что при использовании ORM SQLAlchemy эти объекты обычно не доступны; вместо этого объект Session используется как интерфейс к базе данных. Однако для приложений, которые основаны на прямом использовании текстовых операторов SQL и/или конструкций выражений SQL без участия служб управления более высокого уровня ORM, Engine и Connection являются королем (и королевой?) - читайте дальше.