Как выполнить raw SQL в приложении SQLAlchemy-flask


Как вы выполняете raw SQL в SQLAlchemy?

У меня есть веб-приложение python, которое работает на flask и взаимодействует с базой данных через SQLAlchemy.

Мне нужен способ запуска необработанного SQL. Запрос включает в себя несколько соединений таблиц вместе со встроенными представлениями.

Я пробовал:

connection = db.session.connection()
connection.execute( <sql here> )

но я продолжаю получать ошибки шлюз.

6 132

6 ответов:

вы пробовали:

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

или:

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

если вы хотите использовать сессии (как ваш вопрос), используйте его 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})

следующее Может быть специфичным для моего драйвера базы данных (psycopg2); я не уверен. Независимо от того, как я вытаскиваю свои ценности.

from collections import namedtuple

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

ключевым моментом является fetchall() звонок. Элемент namedtuple часть просто то, что я нахожу делает мою жизнь проще, давая имя на основе доступа.

кроме того, это транзакционные без управлять им вручную. Скажи make_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()

документы: учебник по языку выражений 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')

вы можете получить результаты выбора SQL-запросов с помощью from_statement() и text() как показано здесь. Вы не должны иметь дело с тупулес таким образом. В качестве примера для пользователя класса, имеющего имя таблицы "пользователи", Вы можете попробовать,

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>"))

выполняет <sql here> но не совершает его, если вы не находитесь на autocommit режим. Таким образом, вставки и обновления не будут отражаться в базе данных.

чтобы совершить после изменений, сделайте

result = db.engine.execute(text("<sql here>").execution_options(autocommit=True))

вы пробовали использовать connection.execute(text( <sql here> ), <bind params here> ) и привязать параметры, как описано в документах? Это может помочь решить многие проблемы форматирования параметров и производительности. Может быть, ошибка шлюза-это тайм-аут? Параметры привязки, как правило, делают сложные запросы выполняются значительно быстрее.