2011-11-06 1 views
13

介して挿入項目を削除するには、私は、このようなこの一つとしてエラーが出る問題抱えている:だからSQLAlchemyのStaleDataErrorは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. 

を、私は何が良いアイデアを持っています問題を引き起こしていますが、私はそれを解決することができませんでした。

私はpage_iduser_idに外部キーを持つpage_viewモデルを持っています。ここで

は、モデルは次のようになります。

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

ここで私は、INSERT文を使用して、私のデータベースにこれに似たようないくつかの項目を追加してい関係は

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

のように見えるものです:

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) 

ログからわかるように、トランザクションはコミットされます適切に私はDBの項目を参照してください。

しかし、ORMを使用してページアイテムを削除しようとすると、StaleDataError例外が発生します。ログを見ると、ORMはdelete文を発行していますが、エラーのためにロールバックしています。

私はsession.expire_all()と同様にsession.expunge_all()を試してみましたが、挿入ステートメントの直後にはそれらはあまり役に立ちませんでしたが、私はまだエラーです。

これは、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 

私は、二重のdelete文が容疑者だと思ったかもしれない設定に誤りORMの関係を指すが、私はそうではないと思います。

答えて

3

私はヒントこの問題を与えることができると思います。短いバージョンは、「問題を解決するためにデータベース内のデータを手動で変更する必要があるかもしれません」というものです。

長いバージョン:私はSQLiteで同様の問題がありました。私は次の表をマッピングしました:

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

複合主キーを参照してください。私は何とか同じrecipe_title/product_titleペアで2つの行を挿入することができました。私はこのテーブルのSQLiteの側に単一の制約がないことを知りました(プライマリキーなし、正当なキーなし - 単純なバニラテーブルでした)。しかし、sqlalchemyが行く方法ではなく、ビジネス。

これらの2つの行を含むオブジェクトを削除しようとすると、sqlalchemyは制約が違反されていることを確認し、 'StaleDataError'をスローしました。最後に、SQLiteテーブルから手動で行を1つずつ削除するだけでした。

1

カラムにはprimary_keyというマークを付けることができますが、これはデータベースレベルでも同様に強制されていることを確認してください(データベースが別のツールで作成された場合など)。 MySQLでは、これはPRIMARY KEYであり、KEYであることを保証することを意味します。

私の場合、primary_key(コンポジット)とマークされた2つの列がありましたが、同じ(おそらく)ユニークなidのものを含む複数の行がありました。

+0

このような回答を改善するには、「列にはprimary_keyとしてマークすることができますが、データベースはそのように強制することはできませんが、」を実行してKEYではなくPRIMARY KEYであることを確認してください。これは元の質問への回答ではありませんそれを削除してください。 –