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

Kri*_*oit 3 python polymorphism sqlalchemy 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',
  }
Run Code Online (Sandbox Code Playgroud)

这是我删除它的方法:

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

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

q.delete(False)
Run Code Online (Sandbox Code Playgroud)

我收到以下错误,这是一个错误还是我的操作方式错误?

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

我期望 sqlalchemy 删除工程师和员工表中的条目。

Hal*_*Ali 5

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

id = Column(Integer, ForeignKey('employee.id', ondelete='CASCADE'), primary_key=True)
Run Code Online (Sandbox Code Playgroud)

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

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

for eng in eng_list:
   session.delete(eng)
session.commit()
Run Code Online (Sandbox Code Playgroud)

Employee这将从和表中删除记录Engineer

更新:对错误消息的评论:

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

您尝试尝试通过加入 Employee 从 Engineer 中删除(以访问字段 Employee.name)。但是 sqlalchemy 发送到后端的查询中缺少此连接。

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

更新2:在尊重外键约束(并且onupdate约束已设置为cascade)的后端上,删除父行中的行应该足够了,并且子行中的链接行将被自动删除。

我在 MySQL 和 Postgresql 后端尝试了这个示例,以下查询从两个表 ( employee& engineer) 中删除了该行:

session.query(Employee).filter(Employee.name=='John').delete()
Run Code Online (Sandbox Code Playgroud)

由于某种原因,在 Sqlite 上,这只会删除 中的记录employee