我有一个问题,我得到一个错误,比如这个:
"MyPyramidApplication Error"<class 'sqlalchemy.orm.exc.StaleDataError'>: DELETE statement on table 'page_view' expected to delete 6 row(s); Only 0 were matched.
所以,我很清楚是什么导致了这个问题,但我一直无法解决。
我有一个页面视图模型,它在page_id
和user_id
上有一个外键。
下面是模型的外观:
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'
)
这是他们的关系
orm.mapper(Page, page_table,
properties = {
'users_viewed': sa.orm.relation(
User,
secondary=page_view_table,
backref='page'),
}
)
我正在使用insert语句向数据库中添加一些项,类似于:
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)
从日志中可以看出,事务得到了正确的提交,并且我看到了数据库中的项。
但是,当我尝试使用ORM删除页面项时,会出现StaleDataError异常。查看日志,我看到ORM发出delete语句,但是由于错误而回滚。
我试过在insert语句之后使用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
我认为double delete语句是一个嫌疑犯,可能指向一个配置错误的ORM关系,但我不认为是这样。
尽管可以将列标记为
primary_key
,但也要确保在数据库级别强制执行(例如,当数据库由其他工具创建时)。在MySQL中,这意味着确保它们是PRIMARY KEY
,而不仅仅是KEY
。在我的例子中,有两列标记为
primary_key
(composite),但是有多行包含相同的(假定的)唯一的id
我想我可以给这个问题一个提示。简短的版本是:“您可能需要手动修改数据库中的数据来解决问题”。
更长的版本:我对SQLite也有类似的问题。我映射了下表:
看到复合主键了吗?不知怎么的,我设法插入了两行相同的菜谱标题/产品标题对。我很惊讶地发现,这个表的SQLite端没有一个约束(没有主键,没有fereign键-它只是一个普通的普通表),但是-这就是sqlalchemy的方式,而不是我的业务。
然后当我试图删除一个涉及这两行的persited对象时,sqlalchemy发现它的约束被违反了,并抛出了“StaleDataError”。最后,我不得不从SQLite表中手动删除一个复制行。
相关问题 更多 >
编程相关推荐