web-dev-qa-db-ja.com

SqlAlchemy:最後に挿入されたレコードのIDを取得する

ORMなしでSQLAlchemyを使用しています。つまり、手作りのSQLstatememtsを使用してバックエンドデータベースと直接対話しています。この場合、バックエンドデータベースとしてPGを使用しています(DBドライバーとしてpsycopg2)-それが答えに影響するかどうかはわかりません。

私はこのようなステートメントを持っています(簡潔にするために、connがdbへの有効な接続であると仮定します):

conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)")

また、ユーザーテーブルが列(id [SERIAL PRIMARY KEY]、name、country_id)で構成されていると仮定します。

新しいユーザーのIDを取得するにはどうすればよいですか(理想的には、dbを再度押すことなく)。

24

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")
21

ユーザー lastrowid

result = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)")
result.lastrowid
20
Nilesh

現在のSQLAlchemy ドキュメント 提案

result.inserted_primary_key動作するはずです!

3
Milind Dalvi

この質問はstackoverflowで何度も聞かれましたが、私が見た答えは包括的ではありません。グーグル 'sqlalchemy insert get id of new row'は、それらの多くを表示します。

SQLAlchemyには3つのレベルがあります。上:ORM。中央:テーブルクラスなどを使用したデータベース抽象化(DBA)。下:テキスト関数を使用したSQL。

OOプログラマーにとってはORMレベルは自然に見えますが、データベースプログラマーにとっては見苦しく、ORMが邪魔になります。DBAレイヤーは妥協点として問題ありません。SQLレイヤーはデータベースにとって自然に見えます。プログラマーであり、オブジェクト指向のみのプログラマーには異質に見えます。

各レベルには独自の構文があり、似ていますが、イライラするほど異なっています。これに加えて、オンラインのドキュメントが多すぎて、答えを見つけるのが非常に困難です。

挿入されたIDを取得する方法を説明しますAT使用するRDBMSの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()
1
Mark Kortink
result.inserted_primary_key

私のために働いた。注意すべき唯一のことは、これがそのlast_insert_idを含むリストを返すことです。

0

returningオブジェクトを受け取るには必ずfetchrow/fetchを使用してください

insert_stmt = user.insert().values(name="homer", country_id="123").returning(user.c.id)

row_id = await conn.fetchrow(insert_stmt)
0
Shadycorp