2

以下错误的最可能原因是什么,我该如何解决?我不明白为什么 SQLAlchemy 会生成一个缺少表达式的查询!该代码适用于 SQLite,但在 Oracle 上失败。下面的 SQL 查询有什么问题?

此 Python 代码适用于 SQLite,但在 Oracle 11g 上失败:

q = (session.query(locomotion_class).join(LocomotionLink, LocomotionLink.parent_id == self.id).filter(LocomotionLink.child_id == locomotion_class.id, LocomotionLink.child_id != self.id))
# locomotion_class is any of the subclasses of Locomotion (in this case Virion)
return session.query(q.exists()).scalar()

以上结果导致以下查询:

SELECT EXISTS (
    SELECT 1
    FROM locomotion
    JOIN virion ON locomotion.id = virion.id
    JOIN locomotion_link ON locomotion_link.parent_id = 16
    WHERE locomotion_link.child_id = virion.id AND locomotion_link.child_id != 16
) AS anon_1 FROM DUAL

它适用于 SQLite,但在 Oracle 11g 上失败

"Internal Server Error: (cx.Oracle.DatabaseError) ORA-00936: missing expression"

当我尝试在 sqlplus 中运行生成的表达式时,它在“parent_id = 16”中显示星号低于 6(即直接在 WHERE 之前),但我看不到有任何遗漏。

4

3 回答 3

1

(代表问题作者发布答案,将其从问题移至答案空间)。

根据下面的评论和答案,我实施了以下修复:

return session.query(literal(True)).filter(q.exists()).scalar()
于 2019-10-27T14:28:30.950 回答
1

嗯,是的 -select exists在 Oracle 中是无效的,因为它被用作where子句的一部分,例如

SELECT ...
  FROM ...
 WHERE EXISTS
          (SELECT 1
             FROM locomotion
                  JOIN virion ON locomotion.id = virion.id
                  JOIN locomotion_link ON locomotion_link.parent_id = 16
            WHERE     locomotion_link.child_id = virion.id
                  AND locomotion_link.child_id != 16)

另一方面,您编写的子查询表明它可能是查询返回,例如

SELECT (SELECT 1
          FROM locomotion
               JOIN virion ON locomotion.id = virion.id
               JOIN locomotion_link ON locomotion_link.parent_id = 16
         WHERE     locomotion_link.child_id = virion.id
               AND locomotion_link.child_id != 16)
          AS anon_1
  FROM DUAL

但这有点愚蠢,因为它可能只是

SELECT 1 AS anon_1
  FROM locomotion
       JOIN virion ON locomotion.id = virion.id
       JOIN locomotion_link ON locomotion_link.parent_id = 16
 WHERE     locomotion_link.child_id = virion.id
       AND locomotion_link.child_id != 16

你该怎么办?我不知道。这取决于你想做什么。

于 2019-09-04T11:52:14.457 回答
1

语法

SELECT EXISTS ( <a subquery> ) AS anon_1 FROM DUAL

不适合 Oracle,但更喜欢使用:

SELECT 1 FROM DUAL
WHERE EXISTS 
     (
      SELECT 1
        FROM locomotion
        JOIN virion
          ON locomotion.id = virion.id
        JOIN locomotion_link
          ON locomotion_link.parent_id = 16
       WHERE locomotion_link.child_id = virion.id
         AND locomotion_link.child_id != 16
     )
于 2019-09-04T11:52:47.550 回答