2011-11-06 13 views
13

sto avendo un problema in cui ottengo un errore come questo:SQLAlchemy StaleDataError sulla eliminazione di elementi inseriti tramite ORM sqlalchemy.orm.exc.StaleDataError

"MyPyramidApplication Error"<class 'sqlalchemy.orm.exc.StaleDataError'>: DELETE statement on table 'page_view' expected to delete 6 row(s); Only 0 were matched. 

Quindi, ho una buona idea di che cosa sta causando il problema ma non sono stato in grado di risolverlo.

Ho un modello page_view, che ha una chiave esterna su page_id e un user_id.

Ecco ciò che il modello si presenta come:

page_view_table = sa.Table(
    'page_view', 
    metadata, 
    sa.Column('id', sa.Integer, primary_key=True), 
    sa.Column('page_id', sa.Integer, sa.ForeignKey('guide.id')), 
    sa.Column('user_id', sa.Integer, sa.ForeignKey('user.id')), 
    sa.Column('last_view', sa.DateTime, nullable=False), 
    sa.UniqueConstraint('user_id', 'page_id'), 
    mysql_engine='InnoDB', 
    mysql_charset='utf8mb4' 
) 

Ecco quello che i rapporti sembrano

orm.mapper(Page, page_table, 
    properties = { 
     'users_viewed': sa.orm.relation(
      User, 
      secondary=page_view_table, 
      backref='page'), 
    } 
) 

sto aggiungendo alcuni elementi a mio database utilizzando un'istruzione INSERT, qualcosa di simile a questo:

ins = model.page_view_table.insert() 
sql = str(ins) 
sql += ' ON DUPLICATE KEY UPDATE last_view = :last_view' 
session = model.Session() 
session.execute(sql, page_views) 
mark_changed(session) 

per quanto mi riguarda posso dire dai registri, le operazioni ottiene commesso correttamente e vedo gli elementi nel DB.

Tuttavia, quando provo a eliminare l'elemento della pagina utilizzando l'ORM, ottengo l'eccezione StaleDataError. Guardando i registri, vedo l'ORM che emette un'istruzione delete ma che poi ritorna indietro a causa dell'errore.

Ho provato a sperimentare con session.expire_all() e session.expunge_all() subito dopo l'istruzione di inserimento ma non sono stati molto utili e ho ancora l'errore.

Ecco cosa vedo nei registri di SQLAlchemy.

2011-11-05 18:06:08,031 INFO [sqlalchemy.engine.base.Engine][worker 3] DELETE FROM page_view WHERE page_view.page_id = %s AND page_view.user_id = %s 
2011-11-05 18:06:08,031 INFO [sqlalchemy.engine.base.Engine][worker 3] (13818L, 259L) 
2011-11-05 18:06:08,032 INFO [sqlalchemy.engine.base.Engine][worker 3] DELETE FROM page_view WHERE page_view.page_id = %s AND page_view.user_id = %s 
2011-11-05 18:06:08,033 INFO [sqlalchemy.engine.base.Engine][worker 3] (13818L, 259L) 
2011-11-05 18:06:08,033 INFO [sqlalchemy.engine.base.Engine][worker 3] ROLLBACK 

ho pensato la dichiarazione doppia eliminazione era un sospetto, forse indicando una relazione ORM mal configurato, ma non credo che sia il caso.

risposta

3

Immagino di poter dare un suggerimento su questo problema. La versione breve è: "Probabilmente dovrai modificare manualmente i dati nel Database per risolvere il problema".

La versione più lunga: ho avuto un problema simile con SQLite. Ho avuto la seguente tabella mappata:

ingredients = Table('ingredients', metadata, 
    Column('recipe_title', Unicode, ForeignKey('recipes.title'), primary_key=True), 
    Column('product_title', Unicode, ForeignKey('products.title'), primary_key=True), 
    Column('amount', Integer, nullable=False), 
    Column('unit_title', Unicode, ForeignKey('units.title'))) 

vedere quella chiave primaria composita? Sono riuscito in qualche modo a inserire due righe con la stessa coppia recipe_title/product_title. Ero sorpreso di scoprire che non c'era un solo vincolo sul lato di SQLite per questo tavolo (nessuna chiave primaria, nessuna chiave di riconoscimento - era solo un semplice tavolo di vaniglia), ma bene - questo è il modo in cui va in sqlalchemy, non il mio attività commerciale.

Poi, quando ho provato a eliminare un oggetto persistente che coinvolge quelle due righe, sqlalchemy ha visto che i suoi vincoli sono stati violati e ha lanciato lo 'StaleDataError'. Alla fine ho dovuto rimuovere una riga duplicata manualmente dalla tabella SQLite.

1

Sebbene le colonne possano essere contrassegnate come primary_key, assicurarsi che questo sia applicato anche a livello di database (ad esempio quando il database è stato creato da uno strumento diverso). In MySQL questo significa assicurare che siano PRIMARY KEY e non solo KEY.

Nel mio caso c'erano 2 colonne contrassegnate come primary_key (composito) ma c'erano più righe contenenti lo stesso (apparentemente) unico id.

+0

Per migliorare questa risposta, si prega di riformulare --- come "Sebbene le colonne possano essere contrassegnate come primary_key il database potrebbe non applicarle come tali. Assicurarsi che siano PRIMARY KEY e non KEY eseguendo " O se questa non è una risposta alla domanda originale, per favore cancellala. –

Problemi correlati