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.

132
demandé sur Eric Leschinski 2013-07-31 17:39:42

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
202
répondu Miguel 2016-01-11 12:05:11

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()
98
répondu jpmc26 2017-10-24 19:21:15

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')
44
répondu Jake Berger 2018-01-30 17:29:56

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
23
répondu TrigonaMinima 2014-11-03 12:39:44
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))
9
répondu Devi 2017-12-13 14:30:31

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.

0
répondu jhnwsk 2013-09-15 11:06:01