Работа с транзакциями и DBAPI¶
Engine Engine Connection Result facade Session W
Примечание для читателей ORM.
Session Session Connection Connection Session а
:func:`_sql.text`Как
Получение соединения¶
Connection в результат Connection Connection the with statement text() е
>>> from sqlalchemy import text
>>> with engine.connect() as conn:
... result = conn.execute(text("select 'hello world'"))
... print(result.all())
{execsql}BEGIN (implicit)
select 'hello world'
[...] ()
{stop}[('hello world',)]
{execsql}ROLLBACK{stop}released`В т :meth:`_engine.Connection.commit .
Совет
:ref:`dbapi_autocommit`В т.
:class:`_engine.Result`Ре
Зафиксировать изменения¶
commit`М :class:`_engine.Connection() ы
# "commit as you go"
>>> with engine.connect() as conn:
... conn.execute(text("CREATE TABLE some_table (x int, y int)"))
... conn.execute(
... text("INSERT INTO some_table (x, y) VALUES (:x, :y)"),
... [{"x": 1, "y": 1}, {"x": 2, "y": 4}],
... )
... conn.commit()
{execsql}BEGIN (implicit)
CREATE TABLE some_table (x int, y int)
[...] ()
<sqlalchemy.engine.cursor.CursorResult object at 0x...>
INSERT INTO some_table (x, y) VALUES (?, ?)
[...] [(1, 1), (2, 4)]
<sqlalchemy.engine.cursor.CursorResult object at 0x...>
COMMITtutorial_multiple_parameters`A :meth:`_engine.Connection.commit Connection.commit() b
Engine.connect() Connection r
# "begin once"
>>> with engine.begin() as conn:
... conn.execute(
... text("INSERT INTO some_table (x, y) VALUES (:x, :y)"),
... [{"x": 6, "y": 8}, {"x": 9, "y": 10}],
... )
{execsql}BEGIN (implicit)
INSERT INTO some_table (x, y) VALUES (?, ?)
[...] [(6, 8), (9, 10)]
<sqlalchemy.engine.cursor.CursorResult object at 0x...>
COMMITСтиль «Начать один раз» часто предпочтительнее, поскольку он более лаконичен и заранее указывает на замысел всего блока. Однако в рамках данного учебника мы будем использовать стиль «commit as you go», поскольку он более гибок для демонстрационных целей.
Основы выполнения выписок¶
execute`М :func:`_sql.text() Result ы
Connection.execute() Result o
Получение строк¶
:class:`_engine.Result`Мы
>>> with engine.connect() as conn:
... result = conn.execute(text("SELECT x, y FROM some_table"))
... for row in result:
... print(f"x: {row.x} y: {row.y}")
{execsql}BEGIN (implicit)
SELECT x, y FROM some_table
[...] ()
{stop}x: 1 y: 1
x: 2 y: 4
x: 6 y: 8
x: 9 y: 10
{execsql}ROLLBACK{stop}:class:`_engine.Result`Ab
<<<0>> Result.all() Row Row >
В качестве параметра Row выступае named tuples т
Присвоение кортежей - это наиболее идиоматичный стиль Python, который заключается в позиционном присваивании переменных каждой строке по мере их поступления:
result = conn.execute(text("select x, y from some_table")) for x, y in result: ...
Integer Index - Кортежи представляют собой последовательности Python, поэтому возможен и обычный доступ к целым числам:
result = conn.execute(text("select x, y from some_table")) for row in result: x = row[0]
Имя атрибута - поскольку это именованные кортежи Python, кортежи имеют динамические имена атрибутов, совпадающие с именами каждого столбца. Эти имена обычно соответствуют именам, которые SQL-оператор присваивает столбцам в каждой строке. Хотя обычно они достаточно предсказуемы и могут также управляться метками, в менее определенных случаях они могут быть подвержены специфическому для базы данных поведению:
result = conn.execute(text("select x, y from some_table")) for row in result: y = row.y # illustrate use with Python f-strings print(f"Row: {row.x} {y}")
dictResultMappingResultResult.mappings()RowMappingRow*result = conn.execute(text("select x, y from some_table")) for dict_row in result.mappings(): x = dict_row["x"] y = dict_row["y"]
Параметры отправки¶
Connection.execute`S :term:`bound parameters() Q
text() :y :y Connection.execute() В
>>> with engine.connect() as conn:
... result = conn.execute(text("SELECT x, y FROM some_table WHERE y > :y"), {"y": 2})
... for row in result:
... print(f"x: {row.x} y: {row.y}")
{execsql}BEGIN (implicit)
SELECT x, y FROM some_table WHERE y > ?
[...] (2,)
{stop}x: 2 y: 4
x: 6 y: 8
x: 9 y: 10
{execsql}ROLLBACK{stop}``:y``В т.
Всегда используйте связанные параметры
Как уже упоминалось в начале этого раздела, текстовый SQL не является обычным способом работы с SQLAlchemy. Однако при использовании текстового SQL буквальные значения Python, даже нестроковые, такие как целые числа или даты, никогда не должны стробироваться в строку SQL напрямую; всегда используется параметр. Это наиболее известный способ избежать атак SQL-инъекций, когда данные не являются доверенными. Однако это также позволяет диалектам SQLAlchemy и/или DBAPI корректно обрабатывать входящие данные для бэкенда. За пределами случаев использования обычного текстового SQL, SQLAlchemy’s Core Expression API обеспечивает передачу буквальных значений Python в качестве связанных параметров, где это необходимо.
Отправка нескольких параметров¶
tutorial_committing_data`В т :term:`DML Connection.execute() executemany .
>>> with engine.connect() as conn:
... conn.execute(
... text("INSERT INTO some_table (x, y) VALUES (:x, :y)"),
... [{"x": 11, "y": 12}, {"x": 13, "y": 14}],
... )
... conn.commit()
{execsql}BEGIN (implicit)
INSERT INTO some_table (x, y) VALUES (?, ?)
[...] [(11, 12), (13, 14)]
<sqlalchemy.engine.cursor.CursorResult object at 0x...>
COMMITВ качестве примера можно привести
insert() Использование операторов INSERT Insert.returning() A
Выполнение с помощью сеанса ORM¶
Как уже говорилось, большинство паттернов и примеров, приведенных выше, применимы и к использованию ORM, поэтому здесь мы представим их использование, чтобы по ходу обучения мы могли проиллюстрировать каждый паттерн с точки зрения совместного использования Core и ORM.
Connection по сравнению Session с предыдущими Connection годами, были получены следующие результаты
Connection а
В качестве параметра Session Connection h
>>> from sqlalchemy.orm import Session
>>> stmt = text("SELECT x, y FROM some_table WHERE y > :y ORDER BY x, y")
>>> with Session(engine) as session:
... result = session.execute(stmt, {"y": 6})
... for row in result:
... print(f"x: {row.x} y: {row.y}")
{execsql}BEGIN (implicit)
SELECT x, y FROM some_table WHERE y > ? ORDER BY x, y
[...] (6,){stop}
x: 6 y: 8
x: 9 y: 10
x: 11 y: 12
x: 13 y: 14
{execsql}ROLLBACK{stop}tutorial_sending_parameters`Эк ``with engine.connect() as conn` with Session(engine) as session Session.execute() Connection.execute() с
Session Session.commit() l
>>> with Session(engine) as session:
... result = session.execute(
... text("UPDATE some_table SET y=:y WHERE x=:x"),
... [{"x": 9, "y": 11}, {"x": 13, "y": 15}],
... )
... session.commit()
{execsql}BEGIN (implicit)
UPDATE some_table SET y=? WHERE x=?
[...] [(11, 9), (15, 13)]
COMMIT{stop}:ref:`tutorial_multiple_parameters`Ab
Совет
В качестве источника информации используется Session Connection Connection Engine d
В качестве параметра Session выступае Session.execute() Connection.execute() т
См.также
SQLAlchemy 1.4 / 2.0 Tutorial
Следующий учебный раздел: Работа с метаданными базы данных