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

时间:2013-07-31 13:39:42

标签: python sql sqlalchemy flask flask-sqlalchemy

如何在SQLAlchemy中执行原始SQL?

我有一个python web应用程序,它运行在烧瓶上,并通过SQLAlchemy与数据库连接。

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

我试过了:

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

但我一直遇到网关错误。

9 个答案:

答案 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

从 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)

如果要避免元组,另一种方法是调用firstoneall方法:

query = db.engine.execute("SELECT * FROM blogs "
                           "WHERE id = 1 ")

assert query.first().name == "Welcome to my blog"