【问题标题】:Get last inserted value from MySQL using SQLAlchemy使用 SQLAlchemy 从 MySQL 获取最后插入的值
【发布时间】:2011-12-21 05:14:06
【问题描述】:

我刚刚遇到了一个相当棘手的问题,经过测试,我发现没有一个可用的答案是足够的。

我看到了各种建议,但似乎没有一个能够返回 MySQL 中 auto_increment 字段的最后插入值。

我见过提到使用 session.flush() 添加记录然后检索 id 的示例。然而,这似乎总是返回 0。

我还看到提到使用 session.refresh() 的示例,但会引发以下错误:InvalidRequestError: Could not refresh instance ''

我正在尝试做的事情看起来非常简单,但我似乎无法弄清楚其中的秘密。

我正在使用声明式方法。

所以,我的代码看起来像这样:

class Foo(Base):
    __tablename__ = 'tblfoo'
    __table_args__ = {'mysql_engine':'InnoDB'}

    ModelID = Column(INTEGER(unsigned=True), default=0, primary_key=True, autoincrement=True)
    ModelName = Column(Unicode(255), nullable=True, index=True)
    ModelMemo = Column(Unicode(255), nullable=True)

f = Foo(ModelName='Bar', ModelMemo='Foo')
session.add(f)
session.flush()

此时,对象 f 已经被推送到 DB,并被自动分配了唯一的主键 id。但是,我似乎无法找到一种方法来获取在某些附加操作中使用的值。我想做以下事情:

my_new_id = f.ModelID

我知道我可以简单地执行另一个查询来根据其他参数查找 ModelID,但如果可能的话,我不希望这样做。

我将非常感谢任何对此问题的解决方案的见解。

提前感谢您的帮助。

【问题讨论】:

    标签: python mysql sqlalchemy declarative


    【解决方案1】:

    问题是您将defaul 设置为自动增量。所以当它运行插入查询时,服务器的日志是

    2011-12-21 13:44:26,561 INFO sqlalchemy.engine.base.Engine.0x...1150 INSERT INTO tblfoo (`ModelID`, `ModelName`, `ModelMemo`) VALUES (%s, %s, %s)
    2011-12-21 13:44:26,561 INFO sqlalchemy.engine.base.Engine.0x...1150 (0, 'Bar', 'Foo')
    ID : 0
    

    所以输出是0,这是默认值,因为您正在为autoincrement 列设置默认值。

    如果我在没有default 的情况下运行相同的代码,那么它会给出正确的输出。

    请试试这个代码

    from sqlalchemy import create_engine
    engine = create_engine('mysql://test:test@localhost/test1', echo=True)
    
    from sqlalchemy.ext.declarative import declarative_base
    Base = declarative_base()
    
    from sqlalchemy.orm import sessionmaker
    Session = sessionmaker(bind=engine)
    
    session = Session()
    
    from sqlalchemy import Column, Integer, Unicode
    
    class Foo(Base):
        __tablename__ = 'tblfoo'
        __table_args__ = {'mysql_engine':'InnoDB'}
    
        ModelID = Column(Integer, primary_key=True, autoincrement=True)
        ModelName = Column(Unicode(255), nullable=True, index=True)
        ModelMemo = Column(Unicode(255), nullable=True)
    
    Base.metadata.create_all(engine)
    
    f = Foo(ModelName='Bar', ModelMemo='Foo')
    session.add(f)
    session.flush()
    
    print "ID :", f.ModelID
    

    【讨论】:

    • 不错,没注意到默认值=0。
    • 呃...是的,不错的收获。我的头脑是在 SQL 世界中,当您创建表时,主键字段需要默认值。感谢您的发现。
    【解决方案2】:

    尝试使用session.commit() 而不是session.flush()。然后你可以使用f.ModelID

    【讨论】:

    • 我在刷新和提交后都试过了,但收到以下错误:AttributeError: 'Foo' object has no attribute 'id'
    • 抱歉,更新了使用 ModelID 的答案,就像您在架构声明中使用的一样。不过,您可能应该使用id 而不是ModelID
    • 遗憾的是,我已经尝试了很多方法并继续收到以下错误:ObjectDeletedError: Instance '' has been deleted.
    • flush() 是为了清除交易,这就是我建议commit() 的原因。如果这不起作用,那我就迷路了。
    • 如果我使用 commit() 会出现以下错误:ObjectDeletedError: Instance '' has been deleted。如果我只使用 flush() 则值为 0,默认值不是记录的实际插入值。
    【解决方案3】:

    不确定为什么标记的答案对您有用。但就我而言,这实际上并没有将行插入表中。最后我需要打电话给commit()

    所以最后几行代码是:

    f = Foo(ModelName='Bar', ModelMemo='Foo')
    session.add(f)
    session.flush()
    
    print "ID:", f.ModelID
    
    session.commit()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多