2011-12-21 11 views
6

Ho appena incontrato un problema abbastanza irritante e, dopo aver eseguito il test, ho trovato che NONE delle risposte disponibili sono sufficienti.Ottieni l'ultimo valore inserito da MySQL utilizzando SQLAlchemy

Ho visto vari suggerimenti ma nessuno sembra essere in grado di restituire l'ultimo valore inserito per un campo auto_increment in MySQL.

Ho visto esempi che menzionano l'uso di session.flush() per aggiungere il record e recuperare l'id. Tuttavia, che sembra sempre di tornare 0.

Ho anche visto esempi che riportano l'uso di session.refresh(), ma che solleva il seguente errore: InvalidRequestError: Impossibile aggiornare esempio ''

Quello che sto provare a farlo sembra follemente semplice ma non riesco a capire il segreto.

Sto usando l'approccio dichiarativo.

Quindi, il mio codice simile a questa:

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

A questo punto, l'oggetto f è stato spinto al DB, ed è stato assegnato automaticamente un ID univoco chiave primaria. Tuttavia, non riesco a trovare un modo per ottenere il valore da utilizzare in alcune operazioni aggiuntive. Vorrei fare quanto segue:

my_new_id = f.ModelID

So che potrei semplicemente eseguire un'altra query per cercare il ModelID sulla base di altri parametri, ma io preferirei non se possibile.

Apprezzerei molto qualsiasi idea di una soluzione a questo problema.

Grazie per l'aiuto in anticipo.

risposta

9

Il problema è che si sta impostando defaul per l'incremento automatico. Così, quando si esegue la query INSERT INTO il registro di server è

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 

Quindi l'uscita è 0 che è il valore di default e che viene passato perché si sta impostando il valore di default per autoincrement colonna.

Se eseguo lo stesso codice senza default, restituisce l'output corretto.

Si prega di provare questo codice

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

Bella cattura, non ho notato il default = 0. –

+1

Il log del server funzionerà sempre per trovare il problema :) – Nilesh

+1

Ugh ... sì, bella cattura. La mia testa era nel mondo SQL in cui è necessario un valore predefinito per un campo chiave primaria quando si crea la tabella. Grazie per la scoperta. – PlaidFan

1

Provare a utilizzare session.commit() anziché session.flush(). È quindi possibile utilizzare f.ModelID.

+0

ho provato dopo sia il filo e impegno, ma ha ricevuto il seguente errore: AttributeError: oggetto 'Foo' non ha alcun attributo 'id' – PlaidFan

+0

Siamo spiacenti, aggiornato la risposta per usare ModelID come hai usato nella dichiarazione dello schema. Comunque, dovresti probabilmente usare 'id' invece di' ModelID'. –

+0

Purtroppo, ho provato questo approccio in molti modi e continuo a ottenere il seguente errore: ObjectDeletedError: L'istanza '' è stata cancellata. – PlaidFan

1

Non certo perché la risposta contrassegnato funzionato per voi. Ma nel mio caso, questo in realtà non inserisce la riga nel tavolo. Devo chiamare lo commit() alla fine.

Così le ultime righe di codice sono:

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

print "ID:", f.ModelID 

session.commit() 
Problemi correlati