How to execute raw SQL in Flask-SQLAlchemy app How to execute raw SQL in Flask-SQLAlchemy app flask flask

How to execute raw SQL in Flask-SQLAlchemy app


Have you tried:

result = db.engine.execute("<sql here>")

or:

from sqlalchemy import textsql = text('select name from penguins')result = db.engine.execute(sql)names = [row[0] for row in result]print names

Note that db.engine.execute() is "connectionless", which is deprecated in SQLAlchemy 2.0.


SQL Alchemy session objects have their own execute method:

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

All your application queries should be going through a session object, whether they're raw SQL or not. This ensures that the queries are properly managed by a transaction, which allows multiple queries in the same request to be committed or rolled back as a single unit. Going outside the transaction using the engine or the connection puts you at much greater risk of subtle, possibly hard to detect bugs that can leave you with corrupted data. Each request should be associated with only one transaction, and using db.session will ensure this is the case for your application.

Also take note that execute is designed for parameterized queries. Use parameters, like :val in the example, for any inputs to the query to protect yourself from SQL injection attacks. You can provide the value for these parameters by passing a dict as the second argument, where each key is the name of the parameter as it appears in the query. The exact syntax of the parameter itself may be different depending on your database, but all of the major relational databases support them in some form.

Assuming it's a SELECT query, this will return an iterable of RowProxy objects.

You can access individual columns with a variety of techniques:

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

Personally, I prefer to convert the results into namedtuples:

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

If you're not using the Flask-SQLAlchemy extension, you can still easily use a session:

import sqlalchemyfrom sqlalchemy.orm import sessionmaker, scoped_sessionengine = 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 Expression Language Tutorial - Using Text

example:

from sqlalchemy.sql import textconnection = engine.connect()# recommendedcmd = 'select * from Employees where EmployeeGroup = :group'employeeGroup = 'Staff'employees = connection.execute(text(cmd), group = employeeGroup)# or - wee more difficult to interpret the commandemployeeGroup = '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, 'Tim', 'Gurra', 'Staff', '991-509-9284')(1, 'Jim', 'Carey', 'Staff', '832-252-1910')(2, 'Lee', 'Asher', 'Staff', '897-747-1564')(3, 'Ben', 'Hayes', 'Staff', '584-255-2631')