web-dev-qa-db-ja.com

Flask-SQLAlchemyアプリで生のSQLを実行する方法

SQLAlchemyでどのように生のSQLを実行しますか?

フラスコ上で動作し、SQLAlchemyを介してデータベースに接続するPython Webアプリケーションがあります。

生のSQLを実行する方法が必要です。クエリは、インラインビューと共に複数のテーブル結合を含みます。

私はもう試した:

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

しかし、ゲートウェイエラーが発生し続けます。

174
starwing123

やってみました:

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
249
Miguel

SQL Alchemyセッションオブジェクトには、独自のexecuteメソッドがあります。

result = db.session.execute('SELECT * FROM my_table WHERE my_column = :val', {'val': 5})

すべてのクエリは、生のSQLであろうとなかろうと、セッションオブジェクトを通過するはずです。これにより、クエリが適切に トランザクションによって管理される になります。これにより、同じ要求内の複数のクエリを単一のユニットとしてコミットまたはロールバックすることができます。 engine または connection を使用してトランザクションの外側に出ると、微妙なリスクが非常に高まり、破損したデータが残る可能性のあるバグを検出するのが困難になる可能性があります。各要求は1つのトランザクションにのみ関連付けられている必要があります。db.sessionを使用すると、これが確実にアプリケーションに当てはまるようになります。

それが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

個人的には、結果をnamedtuplesに変換することを好みます。

from collections import namedtuple

Record = namedtuple('Record', result.keys())
records = [Record(*r) for r in result.fetchall()]
for r in records:
    print(r)

Flask-SQLAlchemyエクステンションを使用していない場合でも、簡単にセッションを使用できます。

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})
124
jpmc26

docs: SQL式言語チュートリアル - テキストを使う

例:

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')
51
Jake Berger

ここで示されているように from_statement()text()を使ってSELECT SQLクエリの結果を得ることができます 。あなたはこのようにしてタプルに対処する必要はありません。テーブル名が 'users'のクラスUserの例としては、

from sqlalchemy.sql import text
.
.
.
user = session.query(User).from_statement(
    text("SELECT * FROM users where name=:name")).\
    params(name='ed').all()

return user
29
TrigonaMinima
result = db.engine.execute(text("<sql here>"))

autocommitモードになっていない限り、<sql here>を実行しますが、コミットはしません。そのため、挿入や更新はデータベースに反映されません。

変更後にコミットするには、

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

これはFlaskシェルからSQLクエリを実行する方法の簡単な答えです

まず、あなたのモジュールをマッピングし(あなたのモジュール/アプリがプリンシパルフォルダのmanage.pyで、あなたがUNIXオペレーティングシステムにいるなら)、以下を実行してください:

export FLASK_APP=manage

フラスコシェルを実行

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
Luigi Lopez

docs のようにconnection.execute(text( <sql here> ), <bind params here> )とbindパラメータを使ってみましたか?これは、多くのパラメータフォーマットとパフォーマンスの問題を解決するのに役立ちます。たぶんゲートウェイエラーはタイムアウトですか?バインドパラメータは、複雑なクエリの実行速度を大幅に向上させる傾向があります。

0
jhnwsk