Получить последнее вставленное значение из MySQL, используя SQLAlchemy - PullRequest
6 голосов
/ 21 декабря 2011

Я только что столкнулся с довольно неприятной проблемой, и после тестирования я обнаружил, что НИКАКОГО из доступных ответов не достаточно.

Я видел различные предложения, но ни одно из них не может вернуть последнее вставленное значение для поля auto_increment в MySQL.

Я видел примеры, в которых упоминается использование session.flush () для добавления записи и затем получения идентификатора. Однако, кажется, всегда возвращается 0.

Я также видел примеры, в которых упоминается использование session.refresh (), но возникает следующая ошибка: InvalidRequestError: Не удалось обновить экземпляр ''

То, что я пытаюсь сделать, кажется безумно простым, но я, похоже, не могу разгадать секрет.

Я использую декларативный подход.

Итак, мой код выглядит примерно так:

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 был помещен в БД, и ему автоматически был присвоен уникальный идентификатор первичного ключа. Тем не менее, я не могу найти способ получить значение для использования в некоторых дополнительных операциях. Я хотел бы сделать следующее:

my_new_id = f.ModelID

Я знаю, что мог бы просто выполнить другой запрос для поиска ModelID на основе других параметров, но я бы предпочел этого не делать, если это вообще возможно.

Я был бы очень признателен за понимание этой проблемы.

Заранее спасибо за помощь.

Ответы [ 3 ]

9 голосов
/ 21 декабря 2011

Проблема в том, что вы устанавливаете 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
2 голосов
/ 21 декабря 2011

Попробуйте использовать session.commit() вместо session.flush().Затем вы можете использовать f.ModelID.

1 голос
/ 13 декабря 2016

Не уверен, почему помеченный ответ сработал для вас. Но в моем случае это фактически не вставляет строку в таблицу. Мне нужно позвонить commit() в конце.

Итак, последние несколько строк кода:

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

print "ID:", f.ModelID

session.commit()
...