如何在SQLAlchemy中执行原始SQL语句?
我有一个运行在 Flask 上并通过 SQLAlchemy 与数据库交互的 Python Web 应用程序。
我需要一种运行原始 SQL 的方法。此查询涉及多个表连接以及内联视图。
我尝试过:
connection = db.session.connection()
connection.execute( <sql here> )
但我一直收到网关错误。
如何在SQLAlchemy中执行原始SQL语句?
我有一个运行在 Flask 上并通过 SQLAlchemy 与数据库交互的 Python Web 应用程序。
我需要一种运行原始 SQL 的方法。此查询涉及多个表连接以及内联视图。
我尝试过:
connection = db.session.connection()
connection.execute( <sql here> )
但我一直收到网关错误。
你尝试过吗:
result = db.engine.execute("<sql here>")
或者:from sqlalchemy import text
sql = text('select name from penguins')
result = db.engine.execute(sql)
names = [row[0] for row in result]
print names
请注意,db.engine.execute()
是“无连接”的,在SQLAlchemy 2.0中已被废弃。
db.engine.execute(text("<sql here>")).execution_options(autocommit=True))
执行并提交它。 - Devitext(...)
进行包装? - Nam G VUexecute
方法:
result = db.session.execute('SELECT * FROM my_table WHERE my_column = :val', {'val': 5})
所有与应用程序相关的查询都应该通过会话对象进行,无论它们是否是原始 SQL 查询。这样可以确保查询被正确地由事务管理,从而允许在同一请求中提交或回滚多个查询作为单个单元。如果使用engine或connection超出事务范围,则会面临更大的风险,可能会导致难以检测的错误,使您的数据损坏。每个请求应该仅关联一个事务,使用db.session
将确保此事务适用于您的应用程序。
请注意,execute
是为参数化查询设计的。对于查询中的任何输入,请使用参数(例如示例中的:val
)来保护自己免受SQL注入攻击。您可以通过将字典作为第二个参数传递来为这些参数提供值,其中每个键都是参数在查询中出现的名称。参数本身的确切语法可能因您的数据库而异,但所有主要关系型数据库都以某种形式支持它们。
假设这是一个SELECT
查询,这将返回可迭代的 RowProxy
对象。
您可以使用各种技术访问单个列:
for r in result:
print(r[0]) # Access by positional index
print(r['my_column']) # Access by column name as a string
r_dict = dict(r.items()) # convert to dict keyed by column names
个人而言,我更喜欢将结果转换为namedtuple
:
from collections import namedtuple
Record = namedtuple('Record', result.keys())
records = [Record(*r) for r in result.fetchall()]
for r in records:
print(r.my_column)
print(r)
import sqlalchemy
from sqlalchemy.orm import sessionmaker, scoped_session
engine = sqlalchemy.create_engine('my connection string')
Session = scoped_session(sessionmaker(bind=engine))
s = Session()
result = s.execute('SELECT * FROM my_table WHERE my_column = :val', {'val': 5})
results = db_session.query("my_table")........ .all()
,然后使用for row in results:
,接着row.my_column
就可以工作了。如果你有一个变量存储列名,那么我建议使用getattr(row, column_name_str_variable)
。 - jave.webfrom_statement()
和 text()
来获取 SELECT SQL 查询的结果,如此示例所示 此处。这样你就不必处理元组。例如对于一个名为User
,表名为users
的类,你可以尝试:from sqlalchemy.sql import text
user = session.query(User).from_statement(
text("""SELECT * FROM users where name=:name""")
).params(name="ed").all()
return user
示例:
from sqlalchemy.sql import text
connection = engine.connect()
# recommended
cmd = 'select * from Employees where EmployeeGroup = :group'
employeeGroup = 'Staff'
employees = connection.execute(text(cmd), group = employeeGroup)
# or - wee more difficult to interpret the command
employeeGroup = 'Staff'
employees = connection.execute(
text('select * from Employees where EmployeeGroup = :group'),
group = employeeGroup)
# or - notice the requirement to quote 'Staff'
employees = connection.execute(
text("select * from Employees where EmployeeGroup = 'Staff'"))
for employee in employees: logger.debug(employee)
# output
(0, 'Tim', 'Gurra', 'Staff', '991-509-9284')
(1, 'Jim', 'Carey', 'Staff', '832-252-1910')
(2, 'Lee', 'Asher', 'Staff', '897-747-1564')
(3, 'Ben', 'Hayes', 'Staff', '584-255-2631')
==
吗? - Nam G VU=
通常用于 _赋值_;而 ==
则用于 比较 值。 - Jake Berger从SQLAlchemy 1.4开始,连接或隐式执行已被弃用,即:
db.engine.execute(...) # DEPRECATED
新 API 需要显式连接,例如:
同时支持作为查询的裸字符串。
from sqlalchemy import text
with db.engine.connect() as connection:
result = connection.execute(text("SELECT * FROM ..."))
for row in result:
# ...
同样地,如果有现成的Session可用,鼓励使用:
result = session.execute(sqlalchemy.text("SELECT * FROM ..."))
或使用参数:
session.execute(sqlalchemy.text("SELECT * FROM a_table WHERE a_column = :val"),
{'val': 5})
请参见文档中的"Connectionless Execution, Implicit Execution"了解更多详情。
result = db.engine.execute(text("<sql here>"))
执行<sql here>
语句,但如果不处于autocommit
模式,则不会提交。因此,插入和更新操作不会反映在数据库中。
要提交更改,请执行以下操作:
result = db.engine.execute(text("<sql here>").execution_options(autocommit=True))
export FLASK_APP=manage
运行 Flask shell
flask shell
导入我们需要的内容:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
from sqlalchemy import text
运行您的查询:
result = db.engine.execute(text("<sql here>").execution_options(autocommit=True))
这使用当前应用程序具有的数据库连接。
users = db.session.execute(db.select(User).order_by(User.title.desc()).limit(150)).scalars()
基本上,对于最新稳定版本的 flask-sqlalchemy,特别是文档建议使用session.execute()
方法与db.select(Object)
结合使用。
connection.execute(text( <sql here> ), <bind params here> )
并按照文档所述绑定参数吗?这可以帮助解决许多参数格式和性能问题。也许网关错误是超时引起的?绑定参数往往使复杂查询执行速度大大加快。
connection.execute(text(<sql here>), <bind params>)
。bind params
不应该在text()
中。将绑定参数提供给execute()方法即可。 - Jake Berger如果你想避免元组,另一种方法是通过调用first
、one
或all
方法:
query = db.engine.execute("SELECT * FROM blogs "
"WHERE id = 1 ")
assert query.first().name == "Welcome to my blog"
namedtuple
和dict
的游标:http://initd.org/psycopg/docs/extras.html。 - jpmc26