SQLAlchemyでどのように生のSQLを実行しますか?
フラスコ上で動作し、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
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
個人的には、結果をnamedtuple
sに変換することを好みます。
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})
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')
ここで示されているように 、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
result = db.engine.execute(text("<sql here>"))
autocommit
モードになっていない限り、<sql here>
を実行しますが、コミットはしません。そのため、挿入や更新はデータベースに反映されません。
変更後にコミットするには、
result = db.engine.execute(text("<sql here>").execution_options(autocommit=True))
これは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))
これはアプリケーションを持つ現在のデータベース接続を使用します。
docs のようにconnection.execute(text( <sql here> ), <bind params here> )
とbindパラメータを使ってみましたか?これは、多くのパラメータフォーマットとパフォーマンスの問題を解決するのに役立ちます。たぶんゲートウェイエラーはタイムアウトですか?バインドパラメータは、複雑なクエリの実行速度を大幅に向上させる傾向があります。