2016-10-13 6 views
0

J'utilise une sous-requête pour une opération de jointure. Lorsque je code les paramètres en dur, les choses fonctionnent bien. Mais ces paramètres doivent provenir de sql externe qui, je crois, est appelé requête corrélée. Je voudrais les transmettre en utilisant des alias de table, mais cela donne invalid identifier.Comment utiliser les alias dans une jointure de sous-requête corrélée à Oracle?

Exemple inventé dans le but de la question:

SELECT 
    PR.PROVINCE_NAME 
    ,CO.COUNTRY_NAME 
FROM 
    PROVINCE PR 
    JOIN (
     SELECT COUNTRY_ID, COUNTRY_NAME 
     FROM COUNTRY 
     WHERE COUNTRY_ID=PR.COUNTRY_ID 
    ) CO ON CO.COUNTRY_ID=PR.COUNTRY_ID 
WHERE 
    PR.PROVINCE_ID IN (1,2) 

Ceci est tapé, donc j'espère que je ne l'ai pas présenté de problèmes de syntaxe ici. La question concerne spécifiquement COUNTRY_ID=PR.COUNTRY_ID suite à la clause WHERE. Les alias sont-ils légaux dans de telles sous-requêtes?

+0

Eh bien, dès que je remplacerai 'WHERE COUNTRY_ID = PR.COUNTRY_ID' avec' WHERE COUNTRY_ID = 123', tout fonctionne correctement. Pourrait-il avoir quelque chose à voir avec l'exécution de cette requête via Oracle SQL Developer Version 3.2.09? – user6651485

Répondre

0

Vous utilisez l'alias dans deux emplacements différents. Pour l'un il est légal, pour l'autre il n'est pas:

SELECT pr.province_name, co.country_name 
FROM province pr 
    JOIN (
    SELECT country_id, country_name 
    FROM country 
    WHERE country_id = pr.country_id --<< this reference to the outer table/alias is invalid 
) co ON co.country_id = pr.country_id -- this is valid 
WHERE pr.province_id IN (1,2) 

Avec un (standard) se joindre à une table dérivée, la intérieure select ne peut pas accéder à un alias ou d'une table de la sélection externe. Le "identifiant invalide" que vous obtenez est causé par la ligne WHERE country_id = pr.country_id. Compte tenu de votre condition JOIN, vous pouvez supprimer cela en toute sécurité sans changer le résultat. Et l'optimiseur d'Oracle est assez intelligent pour pousser cette condition dans la table dérivée.

En fait, l'optimiseur va réécrire la requête:

SELECT pr.province_name, co.country_name 
FROM province pr 
    JOIN country co ON co.country_id = pr.country_id 
WHERE pr.province_id IN (1,2); 

Il y a cependant un moyen de la table accès (ou alias) de la requête externe dans une table dérivée: il est appelé latéral rejoindre.

Cela fait partie de la norme SQL, mais vous avez besoin d'Oracle 12 afin de pouvoir l'utiliser:

Le suivant est juridique:

SELECT pr.province_name,co.country_name 
FROM province pr 
    JOIN LATERAL (
     SELECT country_id, country_name 
     FROM country 
     WHERE country_id = pr.country_id 
    ) co ON co.country_id = pr.country_id 
WHERE pr.province_id IN (1,2)
+0

OK. Donc c'est simple alors. J'utilise le ver 11.2 qui n'accepte pas LATERAL. Aussi, j'ai inventé mon exemple pour le but de la question et je ne peux pas réécrire ma requête, comme vous l'avez suggéré. La raison est que j'obtiens plusieurs rangées dans cette jointure et la suquery m'aiderait à réduire à la seule rangée dont j'ai besoin. Merci pour une réponse rapide. – user6651485