如何在SQLAlchemy中执行原始SQL?
我有一个python web应用程序,它运行在烧瓶上,并通过SQLAlchemy与数据库连接。
我需要一种运行原始SQL的方法。该查询涉及多个表连接以及内联视图。
我试过了:
connection = db.session.connection()
connection.execute( <sql here> )
但我一直遇到网关错误。
答案 0 :(得分:248)
你试过了吗?
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
答案 1 :(得分:120)
如果您想使用会话(如您的问题所示),请直接使用其execute
方法:
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})
以下内容可能特定于我的数据库驱动程序(psycopg2);我不确定。无论如何,这是我如何提出我的价值观。
from collections import namedtuple
Record = namedtuple('Record', result.keys())
records = [Record(*r) for r in result.fetchall()]
for r in records:
print(r)
关键是fetchall()
电话。 namedtuple
部分只是通过基于名称的访问权限让我的生活变得更轻松。
此外,这是交易,无需手动管理。说make_session
是一个创建会话的函数:
>>> s1 = make_session()
>>> s1.execute('CREATE TABLE blah (id INTEGER)')
<sqlalchemy.engine.result.ResultProxy object at 0x02CD86F0>
>>> s1.commit()
>>>
>>> s1.execute('INSERT INTO blah VALUES (1)')
<sqlalchemy.engine.result.ResultProxy object at 0x02CD8870>
>>> s1.execute('SELECT * FROM blah').fetchall()
[(1,)]
>>>
>>> s2 = make_session()
>>> s2.execute('SELECT * FROM blah').fetchall()
[]
>>> s2.close()
>>>
>>> s1.commit()
>>>
>>> s2 = make_session()
>>> s2.execute('SELECT * FROM blah').fetchall()
[(1,)]
>>> s2.close()
>>> s1.close()
答案 2 :(得分:51)
docs:SQL Expression Language Tutorial - Using Text
示例:
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, u'Tim', u'Gurra', u'Staff', u'991-509-9284')
(1, u'Jim', u'Carey', u'Staff', u'832-252-1910')
(2, u'Lee', u'Asher', u'Staff', u'897-747-1564')
(3, u'Ben', u'Hayes', u'Staff', u'584-255-2631')
答案 3 :(得分:29)
您可以使用from_statement()
和text()
获取SELECT SQL查询的结果,如图所示here。你不必以这种方式处理元组。作为具有表名'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
答案 4 :(得分:12)
$( document ).ready(function() {
$("#detail").hide();
$("#info").click(function () {
$("#info").hide();
$('#detail').show();
});
$("#detail").click(function () {
$("#info").show();
$("#detail").hide();
});
});
执行result = db.engine.execute(text("<sql here>"))
但不提交,除非您处于<sql here>
模式。因此,插入和更新不会反映在数据库中。
要在更改后提交,请执行
autocommit
答案 5 :(得分:2)
从 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”。
答案 6 :(得分:1)
这是有关如何从Flask Shell运行SQL查询的简化答案
首先,映射您的模块(如果您的模块/应用程序是主体文件夹中的manage.py并且您在UNIX操作系统中),请运行:
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))
运行查询:
{{1}}
这将使用具有应用程序的当前数据库连接。
答案 7 :(得分:0)
您是否尝试使用connection.execute(text( <sql here> ), <bind params here> )
并按照in the docs所述绑定参数?这可以帮助解决许多参数格式和性能问题。也许网关错误是超时?绑定参数往往会使复杂查询执行得更快。
答案 8 :(得分:0)
如果要避免元组,另一种方法是调用first
,one
或all
方法:
query = db.engine.execute("SELECT * FROM blogs "
"WHERE id = 1 ")
assert query.first().name == "Welcome to my blog"