Однострочный обзор:
Поведение execute()
такое же во всех случаях, но они 3 различных методов, в Engine
, Connection
и Session
классы.
Что именно execute()
:
Чтобы понять поведение, execute()
нам нужно заглянуть в Executable
класс. Executable
является суперклассом для всех типов объектов «операторов», включая select (), delete (), update (), insert (), text () - проще говоря, это Executable
конструкция выражения SQL, поддерживаемая в SQLAlchemy.
Во всех случаях execute()
метод принимает текст SQL или сконструированное выражение SQL, то есть любую из разнообразных конструкций выражения SQL, поддерживаемых в SQLAlchemy, и возвращает результаты запроса (a 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()
Явное выполнение без установления соединения, т.е. 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
(Алхимия заботится об этом за вас) и выполняет запрос »- Использование 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 являются королем (и королевой?) - читайте дальше.