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