I use SQLAlchemy and there are at least three entities: engine
, session
and connection
, which have execute
method, so if I e.g. want to select all records from table
I can do this
engine.execute(select([table])).fetchall()
and this
connection.execute(select([table])).fetchall()
and even this
session.execute(select([table])).fetchall()
- the results will be the same.
As I understand it, if someone uses engine.execute
it creates connection
, opens session
(Alchemy takes care of it for you) and executes the query. But is there a global difference between these three ways of performing such a
task?
A one-line overview:
The behavior of
execute()
is same in all the cases, but they are 3 different methods, inEngine
,Connection
, andSession
classes.What exactly is
execute()
:To understand behavior of
execute()
we need to look into theExecutable
class.Executable
is a superclass for all “statement” types of objects, including select(), delete(),update(), insert(), text() - in simplest words possible, anExecutable
is a SQL expression construct supported in SQLAlchemy.In all the cases the
execute()
method takes the SQL text or constructed SQL expression i.e. any of the variety of SQL expression constructs supported in SQLAlchemy and returns query results (aResultProxy
- Wraps aDB-API
cursor object to provide easier access to row columns.)To clarify it further (only for conceptual clarification, not a recommended approach):
In addition to
Engine.execute()
(connectionless execution),Connection.execute()
, andSession.execute()
, it is also possible to use theexecute()
directly on anyExecutable
construct. TheExecutable
class has it's own implementation ofexecute()
- As per official documentation, one line description about what theexecute()
does is "Compile and execute thisExecutable
". In this case we need to explicitly bind theExecutable
(SQL expression construct) with aConnection
object or,Engine
object (which implicitly get aConnection
object), so theexecute()
will know where to execute theSQL
.The following example demonstrates it well - Given a table as below:
Explicit execution i.e.
Connection.execute()
- passing the SQL text or constructed SQL expression to theexecute()
method ofConnection
:Explicit connectionless execution i.e.
Engine.execute()
- passing the SQL text or constructed SQL expression directly to theexecute()
method of Engine:Implicit execution i.e.
Executable.execute()
- is also connectionless, and calls theexecute()
method of theExecutable
, that is, it callsexecute()
method directly on theSQL
expression construct (an instance ofExecutable
) itself.Note: Stated the implicit execution example for the purpose of clarification - this way of execution is highly not recommended - as per docs:
Your questions:
You're right for the part "if someone use
engine.execute
it createsconnection
" but not for "openssession
(Alchemy cares about it for you) and executes query " - UsingEngine.execute()
andConnection.execute()
is (almost) one the same thing, in formal,Connection
object gets created implicitly, and in later case we explicitly instantiate it. What really happens in this case is:At DB layer it's exactly the same thing, all of them are executing SQL (text expression or various SQL expression constructs). From application's point of view there are two options:
Engine.execute()
orConnection.execute()
sessions
- efficiently handles transaction as single unit-of-work, with ease viasession.add()
,session.rollback()
,session.commit()
,session.close()
. It is the way to interact with the DB in case of ORM i.e. mapped tables. Provides identity_map for instantly getting already accessed or newly created/added objects during a single request.Session.execute()
ultimately usesConnection.execute()
statement execution method in order to execute the SQL statement. UsingSession
object is SQLAlchemy ORM's recommended way for an application to interact with the database.An excerpt from the docs:
Nabeel's answer covers a lot of details and is helpful, but I found it confusing to follow. Since this is currently the first Google result for this issue, adding my understanding of it for future people that find this question:
Running .execute()
As OP and Nabell Ahmed both note, when executing a plain
SELECT * FROM tablename
, there's no difference in the result provided.The differences between these three objects do become important depending on the context that the
SELECT
statement is used in or, more commonly, when you want to do other things likeINSERT
,DELETE
, etc.When to use Engine, Connection, Session generally
Engine is the lowest level object used by SQLAlchemy. It maintains a pool of connections available for use whenever the application needs to talk to the database.
.execute()
is a convenience method that first callsconn = engine.connect(close_with_result=True)
and the thenconn.execute()
. The close_with_result parameter means the connection is closed automatically. (I'm slightly paraphrasing the source code, but essentially true).You can use engine to execute raw SQL.
This is covered in the docs under basic usage.
Connection is (as we saw above) the thing that actually does the work of executing a SQL query. You should do this whenever you want greater control over attributes of the connection, when it gets closed, etc. For example, a very import example of this is a Transaction, which lets you decide when to commit your changes to the database. In normal use, changes are autocommitted. With the use of transactions, you could (for example) run several different SQL statements and if something goes wrong with one of them you could undo all the changes at once.
This would let you undo both changes if one failed, like if you forgot to create the datalog table.
So if you're executing raw SQL code and need control, use connections
Sessions are used for the Object Relationship Management (ORM) aspect of SQLAlchemy (in fact you can see this from how they're imported:
from sqlalchemy.orm import sessionmaker
). They use connections and transactions under the hood to run their automatically-generated SQL statements..execute()
is a convenience function that passes through to whatever the session is bound to (usually an engine, but can be a connection).If you're using the ORM functionality, use session; if you're only doing straight SQL queries not bound to objects, you're probably better off using connections directly.