SqlAlchemy:获取插入的最后一条记录的id

Hom*_*lli 19 python postgresql sqlalchemy psycopg2

我在没有ORM的情况下使用SQLAlchemy,即使用手工制作的SQL statememts直接与后端db进行交互.在这种情况下,我使用PG作为我的后端数据库(psycopg2作为数据库驱动程序) - 我不知道这是否会影响答案.

我有这样的语句(为简洁起见,假设conn是与db的有效连接):

conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)")
Run Code Online (Sandbox Code Playgroud)

还假设用户表由列组成(id [SERIAL PRIMARY KEY],name,country_id)

我怎样才能获得新用户的id(理想情况下,无需再次访问db?)

Erw*_*ter 19

您可以像这样使用语句RETURNING子句:INSERT

result = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)
                       RETURNING *")
Run Code Online (Sandbox Code Playgroud)

如果你只想要结果id:

rslt_id = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)
                        RETURNING id")
Run Code Online (Sandbox Code Playgroud)

  • 或者,`user.insert().returns(user.c.id).values({'name':'Homer','country_id':123})` (8认同)
  • 绝对是我需要的.在这两种情况下返回的对象都是ResultProxy,所以我不得不稍微修改一下代码(通过调用fetchone())来使它工作. (2认同)
  • @ErwinBrandstetter我理解这一点,但是sqlalchemy的重点是数据库抽象,因此我刚刚指出,在这种情况下(获取lastrowid)可能是不可能的。 (2认同)

Nil*_*esh 18

用户 lastrowid

result = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)")
result.lastrowid
Run Code Online (Sandbox Code Playgroud)

  • 更具体地说,它不适用于没有oid的表,这是目前的默认值.无论如何,它往往不是你想要的oid:RETURNING是一种优越的解决方案. (6认同)
  • 这不适用于使用psycopg2驱动程序的PG db. (3认同)
  • 感谢MySQL解决方案 (2认同)

Mil*_*lvi 10

当前的 SQLAlchemy文档建议

result.inserted_primary_key 应该管用!


Art*_*nig 7

Python + SQLAlchemy

提交后,您会在对象中更新 primary_key 列 ID(自动增加)。

db.session.add(new_usr)
db.session.commit() #will insert the new_usr data into database AND retrieve id
idd = new_usr.usrID # usrID is the autoincremented primary_key column. 
return jsonify(idd),201 #usrID = 12, correct id from table User in Database.
Run Code Online (Sandbox Code Playgroud)


Mar*_*ink 5

这个问题在 stackoverflow 上被问过很多次,我看到的答案没有一个是全面的。谷歌搜索 'sqlalchemy insert get id of new row' 带来了很多。

SQLAlchemy 分为三个级别。顶部:ORM。中间:具有表类等的数据库抽象 (DBA)。底部:使用文本函数的 SQL。

对于 OO 程序员来说,ORM 级别看起来很自然,但对于数据库程序员来说,它看起来很丑陋,而且 ORM 会成为障碍。DBA 层是一个不错的折衷方案。SQL 层对于数据库程序员来说看起来很自然,而对于只面向 OO 的程序员来说则显得陌生。

每个级别都有自己的语法,相似但不同,足以令人沮丧。最重要的是,在线文档几乎太多,很难找到答案。

我将描述如何为我使用的 RDBMS 在 SQL 层获取插入的 id。

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()
Run Code Online (Sandbox Code Playgroud)