SqlAlchemy: получение идентификатора последней записи
Я использую SQLAlchemy без ORM, то есть используя созданные вручную SQL statememts, чтобы напрямую взаимодействовать с бэкэнд-бэбом. В этом случае я использую PG в качестве моего бэкэнда db (psycopg2 как драйвер DB) - я не знаю, влияет ли это на ответ.
У меня есть такие утверждения (для краткости предположим, что conn является действительным соединением с db):
conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)")
Предположим также, что таблица пользователя состоит из столбцов (id [SERIAL PRIMARY KEY], name, country_id)
Как я могу получить идентификатор нового пользователя (в идеале, не ударяя db снова?)
Ответы
Ответ 1
Возможно, вы можете использовать предложение RETURNING
оператора INSERT
следующим образом:
result = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)
RETURNING *")
Если вам нужен только результирующий id
:
rslt_id = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)
RETURNING id")
Ответ 2
Пользователь lastrowid
result = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)")
result.lastrowid
Ответ 3
В текущей документации SQLAlchemy
result.inserted_primary_key
должен работать!
Ответ 4
result.inserted_primary_key
работал на меня. Единственное, на что следует обратить внимание, это то, что он возвращает список, содержащий этот last_insert_id.
Ответ 5
Убедитесь, что вы используете fetchrow/fetch
для получения объекта returning
insert_stmt = user.insert().values(name="homer", country_id="123").returning(user.c.id)
row_id = await conn.fetchrow(insert_stmt)
Ответ 6
этот вопрос задавался много раз на stackoverflow, и ни один ответ, который я видел, не является исчерпывающим. Погуглив "sqlalchemy insert get id of new row", многие из них поднимаются.
Существует три уровня SQLAlchemy.
Вверху: ОРМ.
Средняя: абстракция базы данных (DBA) с классами таблиц и т.д.
Внизу: SQL с использованием текстовой функции.
Для OO-программиста уровень ORM выглядит естественным, но для программиста базы данных он выглядит уродливо и мешает ORM. Уровень DBA - это хороший компромисс. Уровень SQL выглядит естественным для программистов баз данных и будет выглядеть чуждым только для программиста OO.
Каждый уровень имеет свой собственный синтаксис, похожий, но достаточно различающийся, чтобы расстраивать. Кроме того, в Интернете почти слишком много документации, очень сложно найти ответ.
Я опишу, как получить вставленный идентификатор на уровне SQL для СУБД, которую я использую.
Table: User(user_id integer primary autoincrement key, user_name string)
conn: Is a Connection obtained within SQLAlchemy to the DBMS you are using.
SQLite
======
insstmt = text(
'''INSERT INTO user (user_name)
VALUES (:usernm) ''' )
# Execute within a transaction (optional)
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = result.lastrowid
txn.commit()
MS SQL Server
=============
insstmt = text(
'''INSERT INTO user (user_name)
OUTPUT inserted.record_id
VALUES (:usernm) ''' )
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = result.fetchone()[0]
txn.commit()
MariaDB/MySQL
=============
insstmt = text(
'''INSERT INTO user (user_name)
VALUES (:usernm) ''' )
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = conn.execute(text('SELECT LAST_INSERT_ID()')).fetchone()[0]
txn.commit()
Postgres
========
insstmt = text(
'''INSERT INTO user (user_name)
VALUES (:usernm)
RETURNING user_id ''' )
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = result.fetchone()[0]
txn.commit()