В разделе Работа с транзакциями и DBAPI мы изучили основы взаимодействия с Python DBAPI и его транзакционными состояниями. После, в разделе Работа с метаданными мы выяснили как представлены таблицы, столбцы и ограничения в алхимии, как используя объект метаданных, так и другие связанные объекты. В данном разделе мы научимся объединять эти две концепции чтобы создавать, получать и осуществлять манипуляции с данными. Наше взаимодействие с базой данных всегда будет оставаться транзакционным, даже если мы попросим наш драйвер совершать автоматические сохранения (autocommit) под капотом.

Вставка с помощью Core

При использовании Core, команда SQL INSERT генерируется с помощью функции insert().

<aside> 🌐 В ORM этот процесс зациклен на сессии и происходит при работе такого паттерна как “объединение работ” (unit-of-work). Чисто номинально там нет такого понятия как вставка, но при этом она происходит под капотом при работе с Session.add() и Session.commit()

</aside>

Давайте посмотрим на самый простой пример insert с передачей значений:

from sqlalchemy import insert
stmt = insert(user_table).values(name="spongebob", fullname="Spongebob Squarepants")

Обратите внимание, что выражение SQL было записано в переменную stmt. Практически все такие объекты можно сразу же превратить в строку:

>>> print(stmt)
INSERT INTO user_account (name, fullname) VALUES (:name, :fullname)

Строковое представление создается с помощью компилирования. Мы можем и сами скомпилировать объект выражений с помощью ClauseElement.compile()

compiled = stmt.compile()

Наша с вами конструкция INSERT является также параметризованной, поэтому мы можем посмотреть ее параметры:

>>> compiled.params
{'name': 'spongebob', 'fullname': 'Spongebob Squarepants'}

Выполнение скриптов

Теперь давайте выполним наш SQL скрипт, это мы уже умеем делать

with engine.connect() as conn:
    result = conn.execute(stmt)
    conn.commit()
BEGIN (implicit)
INSERT INTO user_account (name, fullname) VALUES (?, ?)
[...] ('spongebob', 'Spongebob Squarepants')
COMMIT

Этот простой пример показывает, что INSERT не возвращает никакого результата, однако, если вставляется только одна строчка, то мы обычно можем посмотреть данные, автоматически сгенерированные базой данных. Например, в данном случае это будет информация о первичном ключе:

>>> result.inserted_primary_key
(1,)

<aside> ⚠️ Нам возвращается кортеж, это происходит поскольку первичный ключ может быть композитным и состоять из нескольких столбцов.

</aside>

Выражения INSERT всегда генерируют VALUES автоматически