2011-12-21 13 views
6

Acabo de encontrarme con un problema bastante complicado y, después de las pruebas, he encontrado que NINGUNA de las respuestas disponibles es suficiente.Obtener el último valor insertado de MySQL con SQLAlchemy

He visto varias sugerencias pero ninguna parece ser capaz de devolver el último valor insertado para un campo auto_increment en MySQL.

He visto ejemplos que mencionan el uso de session.flush() para agregar el registro y luego recuperar el id. Sin embargo, que siempre parece volver a 0.

También he visto ejemplos que mencionan el uso de session.refresh(), pero esto plantea el siguiente error: InvalidRequestError: No se pudo actualizar instancia ''

Lo que estoy intentar hacerlo parece increíblemente simple, pero parece que no puedo descifrar el secreto.

Estoy usando el enfoque declarativo.

Por lo tanto, mi código es como la siguiente:

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() 

En este punto, el objeto f ha sido empujado a la base de datos, y se le ha asignado automáticamente un único identificador de clave primaria. Sin embargo, parece que no puedo encontrar una manera de obtener el valor para usar en algunas operaciones adicionales. Me gustaría hacer lo siguiente:

my_new_id = f.ModelID

Sé que puede simplemente realizar otra consulta para buscar el ModeloId en base a otros parámetros, pero yo preferiría no, si es posible.

Agradecería cualquier idea de una solución a este problema.

Gracias por la ayuda con antelación.

Respuesta

9

El problema es que está configurando defaul para el incremento automático. Así que cuando se ejecute la consulta de inserción en el registro del servidor es

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 

por lo que la salida es 0 que es el valor por defecto y que se pasa porque está configurando valor predeterminado para autoincrement columna.

Si ejecuto el mismo código sin default, da la salida correcta.

Por favor, intente este código

from sqlalchemy import create_engine 
engine = create_engine('mysql://test:[email protected]/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 
+1

Buena captura, no notó el valor predeterminado = 0. –

+1

El registro del servidor siempre funcionará para encontrar el problema :) – Nilesh

+1

Ugh ... sí, buena captura. Mi cabeza estaba en el mundo de SQL donde se requiere un valor predeterminado para un campo de clave principal cuando se crea la tabla. Gracias por el hallazgo – PlaidFan

1

Intente utilizar session.commit() en lugar de session.flush(). A continuación, puede usar f.ModelID.

+0

lo probé después de que tanto el rubor y me comprometo, pero recibe el siguiente error: AttributeError: objeto 'Foo' no tiene atributo 'id' – PlaidFan

+0

Lo sentimos, actualizado la respuesta para usar ModelID como lo usaste en tu declaración de esquema. Aún así, probablemente debería usar 'id' en lugar de' ModelID'. –

+0

Lamentablemente, he intentado ese enfoque de muchas maneras y continúo obteniendo el siguiente error: ObjectDeletedError: Instance '' ha sido eliminado. – PlaidFan

1

No sé por qué la respuesta marcado trabajó para usted. Pero en mi caso, eso en realidad no inserta la fila en la mesa. Necesito llamar al commit() al final.

Así que las últimas líneas de código son:

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

print "ID:", f.ModelID 

session.commit() 
Cuestiones relacionadas