我使用SQLAlchemy并且至少有三个实体:engine
,session
和connection
,它们具有execute
方法,所以如果我使用想要从table
中选择所有记录我可以这样做
engine.execute(select([table])).fetchall()
和这个
connection.execute(select([table])).fetchall()
甚至这个
session.execute(select([table])).fetchall()
- 结果将是相同的。
据我了解,如果有人使用engine.execute
创建connection
,则会打开session
(Alchemy会为您处理)并执行查询。但这三种表现方式之间是否存在全球差异?
任务?
答案 0 :(得分:82)
一行概述:
execute()
的行为在所有情况下都是相同的,但它们是Engine
,Connection
和Session
类中的3种不同方法。
究竟是什么execute()
:
要了解execute()
的行为,我们需要查看Executable
类。 Executable
是所有“语句”类型对象的超类,包括select(),delete(),update(),insert(),text() - 用最简单的话来说,Executable
是SQLAlchemy支持的SQL表达式构造。
在所有情况下,execute()
方法接受SQL文本或构造的SQL表达式,即SQLAlchemy中支持的各种SQL表达式构造,并返回查询结果(ResultProxy
- 包装一个{{ 1}}游标对象,以便更方便地访问行列。)
进一步澄清(仅用于概念澄清,不是推荐的方法):
除了DB-API
(无连接执行),Engine.execute()
和Connection.execute()
之外,还可以在任何Session.execute()
构造上直接使用execute()
。 Executable
类具有Executable
自己的实现 - 根据官方文档,关于execute()
执行的操作的一行描述是" 编译和执行这个execute()
"。在这种情况下,我们需要显式绑定Executable
(SQL表达式构造)与Executable
对象或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)))
- 将SQL文本或构造的SQL表达式传递给Connection.execute()
的{{1}}方法:
execute()
显式无连接执行,即Connection
- 将SQL文本或构造的SQL表达式直接传递给Engine的engine = create_engine('sqlite:///file.db')
connection = engine.connect()
result = connection.execute(users_table.select())
for row in result:
# ....
connection.close()
方法:
Engine.execute()
隐式执行即execute()
- 也是无连接的,并调用engine = create_engine('sqlite:///file.db')
result = engine.execute(users_table.select())
for row in result:
# ....
result.close()
的{{1}}方法,即调用Executable.execute()
方法直接在execute()
表达式构造(Executable
的一个实例)本身。
execute()
注意:为了澄清,说明了隐式执行示例 - 强烈建议不要使用这种执行方式 - 按docs:
“隐式执行”是一种非常古老的使用模式,在大多数情况下是 比它有用更令人困惑,并且不鼓励使用它。都 模式似乎鼓励过度使用权宜之计的“捷径” 应用程序设计会导致以后出现问题。
据我所知,如果有人使用engine.execute,它会创建连接, 打开会话(Alchemy为你关心它)并执行查询。
你是正确的部分"如果某人使用SQL
,它会创建Executable
"但不是"打开engine = create_engine('sqlite:///file.db')
meta.bind = engine
result = users_table.select().execute()
for row in result:
# ....
result.close()
(Alchemy为你关心它)并执行查询" - 使用engine.execute
和connection
几乎是一样的,在正式的session
对象中隐式创建,在后面的例子中我们显式地实例化它。在这种情况下真正发生的是:
Engine.execute()
但这三种方式之间是否存在全球差异? 执行这样的任务?
在DB层,它完全相同,所有这些都在执行SQL(文本表达式或各种SQL表达式构造)。从应用程序的角度来看,有两种选择:
Connection.execute()
或Connection
`Engine` object (instantiated via `create_engine()`) -> `Connection` object (instantiated via `engine_instance.connect()`) -> `connection.execute({*SQL expression*})`
- 有效地将事务处理为单个事务
通过Engine.execute()
,Connection.execute()
,sessions
,session.add()
轻松完成工作单元。在ORM(即映射表)的情况下,它是与DB交互的方式。提供identity_map以便在单个请求期间立即获取已访问或新创建/添加的对象。 session.rollback()
最终使用session.commit()
语句执行方法来执行SQL语句。使用session.close()
对象是SQLAlchemy ORM推荐的应用程序与数据库交互的方式。
摘自docs:
重要的是要注意当使用SQLAlchemy ORM时,这些 通常不访问对象;相反,Session对象是 用作数据库的接口。但是,对于那些应用程序 围绕直接使用文本SQL语句和/或SQL构建 表达构造没有参与ORM的更高级别 管理服务,发动机和连接是王(和女王?) - 请继续阅读。
答案 1 :(得分:63)
Nabeel's answer涵盖了很多详细信息并且很有帮助,但我发现它很容易引起注意。由于这是目前此问题的第一个Google搜索结果,因此我将其理解为未来发现此问题的人:
OP和Nabell Ahmed都注意到,在执行普通SELECT * FROM tablename
时,所提供的结果没有区别。
根据SELECT
语句的使等等。
引擎是SQLAlchemy使用的最低级别对象。只要应用程序需要与数据库通信,它就可以使用它maintains a pool of connections。 INSERT
是一种便捷方法,首先调用DELETE
,然后调用.execute()
。 close_with_result参数表示连接自动关闭。 (我稍微解释了源代码,但基本上是正确的)。 编辑:Here's the source code for engine.execute
您可以使用引擎执行原始SQL。
conn = engine.connect(close_with_result=True)
basic usage下的文档中介绍了这一点。
连接(如上所述)实际执行SQL查询的工作。每当你想要更好地控制连接的属性,关闭它等等时,你都应该这样做。例如,一个非常重要的例子是Transaction,它允许你决定何时将更改提交给数据库。在正常使用中,更改是自动提交的。通过使用事务,您可以(例如)运行多个不同的SQL语句,如果其中一个出现问题,您可以立即撤消所有更改。
conn.execute()
这可以让你在失败时撤消这两个更改,比如忘记创建数据记录表。
因此,如果您正在执行原始SQL代码并需要控制,请使用连接
会话用于SQLAlchemy的对象关系管理(ORM)方面(事实上,您可以从导入它们的方式看到这一点:result = engine.execute('SELECT * FROM tablename;')
#what engine.execute() is doing under the hood
conn = engine.connect(close_with_result=True)
result = conn.execute('SELECT * FROM tablename;')
#after you iterate over the results, the result and connection get closed
for row in result:
print(result['columnname']
#or you can explicitly close the result, which also closes the connection
result.close()
)。他们使用引擎下的连接和事务来运行自动生成的SQL语句。 connection = engine.connect()
trans = connection.begin()
try:
connection.execute("INSERT INTO films VALUES ('Comedy', '82 minutes');")
connection.execute("INSERT INTO datalog VALUES ('added a comedy');")
trans.commit()
except:
trans.rollback()
raise
是一个便捷函数,它传递给会话绑定的任何内容(通常是引擎,但可以是连接)。
如果您正在使用ORM功能,请使用会话;如果你只做直接的SQL查询没有绑定到对象,你可能最好直接使用连接。
答案 2 :(得分:0)
这是运行诸如GRANT之类的DCL(数据控制语言)的示例
def grantAccess(db, tb, user):
import sqlalchemy as SA
import psycopg2
url = "{d}+{driver}://{u}:{p}@{h}:{port}/{db}".\
format(d="redshift",
driver='psycopg2',
u=username,
p=password,
h=host,
port=port,
db=db)
engine = SA.create_engine(url)
cnn = engine.connect()
trans = cnn.begin()
strSQL = "GRANT SELECT on table " + tb + " to " + user + " ;"
try:
cnn.execute(strSQL)
trans.commit()
except:
trans.rollback()
raise