关于python:如何在SQLAlchemy-flask应用程序中执行原始SQL

How to execute raw SQL in SQLAlchemy-flask app

如何在SQLAlchemy中执行原始SQL?

我有一个python web应用程序,运行在flask上,通过sqlachemy接口到数据库。

我需要一种运行原始SQL的方法。查询涉及多个表联接以及内联视图。

我试过了:

1
2
connection = db.session.connection()
connection.execute( <sql here> )

但我一直在收到网关错误。


您是否尝试过:

1
result = db.engine.execute("<sql here>")

或:

1
2
3
4
5
6
from sqlalchemy import text

sql = text('select name from penguins')
result = db.engine.execute(sql)
names = [row[0] for row in result]
print names


如果您想使用会话(如您的问题所示),请直接使用其execute方法:

1
2
3
4
5
6
7
8
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)特有的;我不确定。不管怎样,这就是我如何提出自己的价值观。

1
2
3
4
5
6
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是一个创建会话的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
>>> 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()


文档:SQL表达式语言教程-使用文本

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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')


您可以使用from_statement()text()获得选择SQL查询的结果,如下所示。你不必用这种方式来处理Tupules。例如,对于具有tablename"users"的类用户,您可以尝试,

1
2
3
4
5
6
7
8
9
from sqlalchemy.sql import text
.
.
.
user = session.query(User).from_statement(
    text("SELECT * FROM users where name=:name")).\
    params(name='ed').all()

return user


1
result = db.engine.execute(text("<sql here>"))

执行,但除非处于autocommit模式,否则不提交。因此,插入和更新不会反映在数据库中。

要在更改后提交,请执行

1
result = db.engine.execute(text("<sql here>").execution_options(autocommit=True))


This is a simplified answer of how to run SQL query from Flask Shell

首先,映射您的模块(如果您的模块/应用程序在主文件夹中是manage.py,而您在UNIX操作系统中),请运行:

1
export FLASK_APP=manage

运行烧瓶外壳

1
flask shell

导入我们需要的内容:

1
2
3
4
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
from sqlalchemy import text

运行查询:

1
result = db.engine.execute(text("<sql here>").execution_options(autocommit=True))

这将使用当前具有应用程序的数据库连接。


您是否尝试过使用connection.execute(text( ), )和docs中描述的绑定参数?这有助于解决许多参数格式和性能问题。也许网关错误是超时?绑定参数往往使复杂查询的执行速度大大加快。