Comment exécutez-vous le SQL brut dans SQLAlchemy?
J'ai une application Web python qui s'exécute sur une fiole et des interfaces avec la base de données via SQLAlchemy.
J'ai besoin d'un moyen d'exécuter le SQL brut. La requête implique plusieurs jointures de table avec des vues incorporées.
J'ai essayé:
connection = db.session.connection()
connection.execute( <sql here> )
Mais je continue à avoir des erreurs de passerelle.
As-tu essayé:
result = db.engine.execute("<sql here>")
ou:
from sqlalchemy import text
sql = text('select name from penguins')
result = db.engine.execute(sql)
names = [row[0] for row in result]
print names
Si vous souhaitez utiliser une session (comme le suggère votre question), utilisez directement sa méthode 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})
Les éléments suivants peuvent être spécifiques à mon pilote de base de données (psycopg2); Je ne suis pas sûr. Peu importe, c'est comme ça que je tire 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 que je trouve me facilite la vie en donnant un accès basé sur le nom.
De plus, il s’agit d’une transaction sans / gestion manuelle. Say 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: Tutoriel SQL Expression Language - Utilisation du 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 SELECT SQL en utilisant from_statement()
et text()
comme indiqué ici . Vous n'avez pas à traiter avec des tupules de cette façon. Comme exemple pour un utilisateur de classe ayant le nom de table 'utilisateurs', 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 commet que si vous êtes en mode autocommit
. Ainsi, les insertions et les mises à jour ne seraient pas reflétées dans la base de données.
Pour valider après les modifications, faites
result = db.engine.execute(text("<sql here>").execution_options(autocommit=True))
Ceci est une réponse simplifiée sur la façon d'exécuter une requête SQL à partir de Shell Flask
Commencez par mapper votre module (si votre module/application est manage.py dans le dossier principal et que vous vous trouvez dans un système d'exploitation UNIX), exécutez:
export FLASK_APP=manage
Run Shell Flask
flask Shell
Importer ce dont nous avons besoin ::
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
from sqlalchemy import text
Exécuter votre requête:
result = db.engine.execute(text("<sql here>").execution_options(autocommit=True))
Ceci utilise la connexion actuelle à la base de données qui contient l'application.
Avez-vous essayé d'utiliser connection.execute(text( <sql here> ), <bind params here> )
et de lier les paramètres comme décrit dans la documentation ? Cela peut aider à résoudre de nombreux problèmes de formatage de paramètres et de performances. Peut-être que l'erreur de passerelle est un délai d'attente? Les paramètres de liaison ont tendance à accélérer considérablement l'exécution des requêtes complexes.