Работа с транзакциями и 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...>
COMMIT
tutorial_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}")
dict
Result
MappingResult
Result.mappings()
RowMapping
Row
*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
Следующий учебный раздел: Работа с метаданными базы данных