使用sqlalchemy多态关系删除整个层次结构

时间:2015-04-16 17:59:08

标签: python sqlalchemy polymorphism polymorphic-associations

我想删除sqlalchemy中具有多态关系的表中的一些元素。这是模型:

class Employee(Base):
  __tablename__ = 'employee'
  id = Column(Integer, primary_key=True)
  name = Column(String(50))
  type = Column(String(50))

  __mapper_args__ = {
    'polymorphic_identity':'employee',
    'polymorphic_on':type
  }

class Engineer(Employee):
  __tablename__ = 'engineer'
  id = Column(Integer, ForeignKey('employee.id'), primary_key=True)
  engineer_name = Column(String(30))

  __mapper_args__ = {
    'polymorphic_identity':'engineer',
  }

以下是我删除它的方法:

e = Engineer();
e.name = "John";
e.engineer_name = "Doe";
DBSession.add(e);

q = session.query(Engineer).filter(Employee.name == "John")

q.delete(False)

我收到以下错误,是一个错误还是我做错了?

sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such
column: employee.name [SQL: u'DELETE FROM engineer WHERE employee.name
= ?'] [parameters: ('John',)]

我期待sqlalchemy删除工程师和员工表中的内容。

2 个答案:

答案 0 :(得分:2)

首先,您应该定义此关系的删除行为:

id = Column(Integer, ForeignKey('employee.id', ondelete='CASCADE'), primary_key=True)

然后,使用ORM,您可以通过循环删除所有名为“John”的工程师:

eng_list = session.query(Engineer).filter(Employee.name == "John").all()

for eng in eng_list:
   session.delete(eng)
session.commit()

这将删除EmployeeEngineer表中的记录。

更新:对错误消息发表评论:

sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such 
column: employee.name [SQL: u'DELETE FROM engineer WHERE employee.name
= ?'] [parameters: ('John',)]

您的尝试尝试从工程师中删除并加入员工(以访问字段Employee.name)。但是sqlalchemy向后端发出的查询中缺少此连接。

我认为SQLite不支持使用连接进行删除。也许您可以尝试针对不同的后端运行session.query(Engineer).filter(Employee.name == "John").delete(),并且sqlalchemy 可以能够发出正确的SQL语句。我没试过。

更新2:在遵守外键约束(以及onupdate约束已设置为cascade)的后端上,删除行中的行应该足够了父行,子项中的链接行将自动删除。

我用MySQL和& amp; Postgresql后端,以下查询删除了两个表中的行(employee& engineer):

session.query(Employee).filter(Employee.name=='John').delete()

出于某种原因,在Sqlite上,这只会从employee删除记录。

答案 1 :(得分:0)

由于不直接支持加入x,我发现一个简单的解决方法是使用常规连接查询选择要删除的ID,然后将这些ID传递给单独的DELETE查询。

一个小麻烦是因为你返回的id是整数,你可能会遇到this error,就像我试图将这些id(技术上是一组元组)直接传递给DELETE查询一样。对字符串的简单中间转换修复了。

所有在一起:

DELETE