2
votes

Quelle peut être la cause la plus probable de «ORA-00936: expression manquante» dans la requête suivante générée par SQLAlchemy?

Quelle est la cause la plus probable de l'erreur suivante et comment puis-je la corriger? Je ne comprends pas pourquoi SQLAlchemy générerait une requête avec une expression manquante! Et le code fonctionne sur SQLite mais échoue sur Oracle. Quel est le problème avec la requête SQL ci-dessous?

Ce code Python fonctionne sur SQLite mais échoue sur Oracle 11g:

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

Les résultats ci-dessus donnent la requête suivante: p >

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

Cela fonctionne sur SQLite mais échoue sur Oracle 11g avec

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()

Lorsque j'essaye d'exécuter l'expression générée dans sqlplus, un astérisque s'affiche moins de 6 ans dans "parent_id = 16" (c'est-à-dire directement avant WHERE) mais je ne vois rien qui manque.


2 commentaires

Je pense que vous devriez lire les notes sur "certaines bases de données" dans docs.sqlalchemy.org/en/13/orm/...


Merci, votre commentaire a été utile!


3 Réponses :


1
votes

Eh bien, oui - select existe n'est pas valide dans Oracle car il doit être utilisé dans le cadre de la clause where , telle que

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

D'un autre côté, la sous-requête que vous avez écrite suggère qu'il pourrait s'agir d'une colonne retour de requête, par exemple

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

mais c'est un peu stupide car cela peut être juste

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)

Que devrais tu faire? Je n'ai aucune idée. Cela dépend de ce que vous voulez faire.


1 commentaires

Merci beaucoup, votre réponse a été très utile!



1
votes

La syntaxe

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
     )

ne convient pas à Oracle, mais préfère utiliser:

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


1 commentaires

Merci de votre aide!



0
votes

(a publié une réponse au nom de l'auteur de la question, pour la déplacer de la question vers l'espace de réponse).

Sur la base du commentaire et des réponses ci-dessous, j'ai implémenté le correctif suivant:

return session.query(literal(True)).filter(q.exists()).scalar()


0 commentaires