SQLAlchemy:使用MySQL上的自联接创建删除查询

时间:2013-02-22 11:58:12

标签: python mysql sql sqlalchemy

我试图在SQLAlchemy + MySQL中复制以下查询而没有运气......

delete paths from paths
join paths as p1 on p1.ancestor = <ID>
where paths.descendant = p1.descendant;

SQLAlchemy似乎忽略了我在删除查询中添加的任何联接。我也尝试使用子查询而不是连接,但是在MySQL中不允许这样做(不能从你想要删除的同一个表中选择)。任何帮助将不胜感激。

更新: 是的,我正在尝试使用ORM层。这是我尝试过的查询:

p1 = aliased(Path, name="p1")
db.session.query(Path).join(
    p1, p1.ancestor==<ID>
)
.filter(
    Path.descendant==p1.Path.descendant
).delete()

和子查询变体,但这对MySQL不起作用,所以对我没用:

q = db.session.query(Path.descendant).filter(Path.ancestor==<ID>).subquery()
db.session.query(Path).filter(Path.descendant.in_(q)).delete(synchronize_session='fetch')

2 个答案:

答案 0 :(得分:2)

SQLAlchemy目前支持Postgresql,MySQL和其他版本的UPDATE..FROM,但我们还没有尝试过支持DELETE..JOIN。

但是,就生成SQL字符串而言,它似乎确实有效(几乎?):

class Path(Base):
    __tablename__ = "path"

    id = Column(Integer, primary_key=True)
    descendant = Column(Integer)
    ancestor = Column(Integer)

j = join(Path, p1, p1.ancestor == 5)
d = delete(j).where(Path.descendant == p1.descendant)
print d

打印:

DELETE FROM path JOIN path AS p1 ON p1.ancestor = :ancestor_1 
 WHERE path.descendant = p1.descendant

然而,我的MySQL数据库不接受这个,默认情况下它会渲染INNER JOIN,但是如果我修改MySQL编译器没有这样做,仍然会失败:

s.execute(d)

(ProgrammingError) (1064, "You have an error in your SQL syntax; check the manual that 
corresponds to your MySQL server version for the
right syntax to use near 'JOIN path AS p1 ON p1.ancestor = 5 WHERE
path.descendant = p1.descendant' at line 1") 'DELETE FROM path JOIN
path AS p1 ON p1.ancestor = %s WHERE path.descendant = p1.descendant'
(5,)

看起来像你的SQL逐字(哦,除了'删除路径来自路径'?是吗?)?

在任何情况下,如果内置编译器没有这样做,您的选择是使用session.execute("some sql")或使用compiler extension构建自定义构造。

答案 1 :(得分:2)

您可以使用prefixes关键字参数:

j = join(table1, table2, table1.c.key==table2.c.key)
stmt = delete(j, prefixes=[table1_name])
session.execute(stmt)

prefixes关键字只是在statement关键字后添加一个或多个表达式,即SELECT,INSERT,UPDATE或DELETE。

在这种情况下,delete(j)语句生成表达式:"DELETE FROM table1 INNER JOIN table2 ON table1.key=table2.key"。 当我们添加prefixes参数表达式变为:"DELETE table1 FROM table1 INNER JOIN table2 ON table1.key=table2.key"时,这是正确的MySQL查询。