Bonjour,
Je développe pour une société un logiciel qui traduit une requête d'un langage de requête propriétaire en une requête SQL.
Mon problème est qu'une des requêtes SQL générée N'EST PAS éxecutable dans Oracle alors qu'elle l'est dans PostgreSQL.
Il me semble qu'oracle me dit qu'il y a une erreur de syntaxe et que je fais référence à une table qui n'a pas été déclarée dans une clause from.
J'utilise Oracle 11.1.0 et PostgreSQL 8.3.
J'ai simplifié le model de BD pour expliquer mon problème : on représente ici des couples de personnes (un organisateur et un participant) qui sont impliqués dans des évènements (mariage, séminaire, sortie mondaine, etc...)
On a donc deux tables Person et Event dans le modèle.
La table Person a un attribut person_id (et d'autres attributs qu'on n'a pas besoin de connaitre pour mon problème).
La table Event a 4 attributs : event_id, event_type, organizer_id et participant_id.
La requête suivante est exécutable dans PostgreSQL mais pas dans Oracle :
Le message d'erreur est ORA-00904: "T2"."C1" : identificateur non valide.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 select t2.c1 as c1 from (select t1.person_id as c1 from person t1) t2 where not exists ( select t3.person_id as c2 from person t3, ( select t5.event_id as c3, t5.organizer_id as c4 from event t5 where (t5.participant_id = t2.c1) ) t4 where (t4.c4 = t3.person_id) )
Pour la rendre exécutable dans Oracle, je modifie la requête en faisant "remonter" la référence "t2.c1" au premier niveau des imbrications :
Mais cela ne résout pas le problème pour le cas général car : pas toutes les "mauvaises" références de ce type sont "remontables".
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 select t2.c1 as c1 from (select t1.person_id as c1 from person t1) t2 where not exists ( select t3.person_id as c2 from person t3, ( select t5.event_id as c3, t5.organizer_id as c4, t5.participant_id as c5 from event t5 ) t4 where ((t4.c4 = t3.person_id) and (t4.c5 = t2.c1)) )
En fait, il me semble que Oracle lève une erreur lorsqu'une référence à une table déclarée "plus haut" est faite dans un from à un niveau d'imbrication égal ou supérieur à 2. Or on peut toujours se débrouiller pour construire des requêtes dont les "mauvaises références" restent coincées à un niveau d'imbrication supérieur ou égal à 2 et ne sont pas "remontables" jusqu'au premier niveau.
Par exemple, on considère une requête avec un double niveau de "not exists" : un "not exists" placé dans une requête placée dans un from lui même participant à une requête qui est placée dans un autre "not exists". On place une référence - comme celle faite à "t2.c1" - dans le "not exists" de plus bas niveau, et la "remontée" de cette référence s'arrête au "not exists" de plus bas niveau. On ne peut pas faire remonter cette référence au dessus du "not exists" sous laquelle elle a été placée. Et entre la déclaration de la table et la référence à cette table il y a toujours un niveau d'imbrication supérieur ou égal à 2. Et oracle est perdu...
Ce genre de requête n'est pas exécutable dans Oracle alors qu'elle l'est toujours dans PostgreSQL (j'en ai testé plusieurs)...
Quelqu'un a-t-il connaissance de ce problème ?
Y-a-t il des solutions ? Peut être que ce bug est-il corrigé dans une version plus récente d'Oracle (si c'est un bug) ?
Olivier
Partager