Comment exécuter du SQL brut dans L'application SQLAlchemy-flask
comment exécuter du SQL brut en SQLAlchemy?
j'ai une application web python qui tourne sur flasque et se connecte à la base de données via SQLAlchemy.
j'ai besoin d'un moyen pour exécuter le SQL brut. La requête implique des jointures de table multiples avec des vues en ligne.
j'ai essayé:
connection = db.session.connection()
connection.execute( <sql here> )
mais je continue à avoir des erreurs de passerelle.
6 réponses
avez-vous essayé:
result = db.engine.execute("<sql here>")
ou:
from sqlalchemy import text
sql = text('select name from penguins')
result = db.engine.execute(sql)
names = []
for row in result:
names.append(row[0])
print names
si vous voulez utiliser une session (comme votre question le suggère), utilisez sa méthode execute
directement:
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})
ce qui suit pourrait être spécifique à mon pilote de base de données (psycopg2); Je ne suis pas sûr. Peu importe, c'est comme ça que je retire mes valeurs.
from collections import namedtuple
Record = namedtuple('Record', result.keys())
records = [Record(*r) for r in result.fetchall()]
for r in records:
print(r)
le point clé est l'appel fetchall()
. La partie namedtuple
est juste quelque chose qui me facilite la vie en donnant un accès par nom.
De plus, il s'agit de la transaction sans la gérer manuellement. Dire make_session
est une fonction qui crée une 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()
docs: SQL Langage d'Expression Tutoriel - Utilisation de Texte
exemple:
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')
vous pouvez obtenir les résultats des requêtes SQL sélectionnées en utilisant from_statement()
et text()
comme indiqué ici . Vous n'avez pas à traiter avec tupules de cette façon. Comme exemple pour un utilisateur de classe ayant le tablename 'users' vous pouvez essayer,
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>"))
exécute le <sql here>
mais ne le commute que si vous êtes en mode autocommit
. Ainsi, les encarts et les mises à jour ne se refléteraient pas dans la base de données.
De s'engager après les changements, faire
result = db.engine.execute(text("<sql here>").execution_options(autocommit=True))
avez-vous essayé d'utiliser connection.execute(text( <sql here> ), <bind params here> )
et de lier les paramètres comme décrit dans le docs ? Cela peut aider à résoudre de nombreux problèmes de formatage de paramètres et de performance. Peut-être que l'erreur de passerelle est un timeout? Les paramètres de Bind ont tendance à accélérer considérablement l'exécution des requêtes complexes.