web-dev-qa-db-fra.com

ORA-00918: colonne définie de manière ambiguë dans SELECT *

Obtention de la colonne de manière ambiguë dans ORA-00918: exécution de ce code SQL:

SELECT *
FROM
  (SELECT DISTINCT(coaches.id),
    people.*,
    users.*,
    coaches.*
  FROM "COACHES"
  INNER JOIN people ON people.id = coaches.person_id
  INNER JOIN users ON coaches.person_id = users.person_id
  LEFT OUTER JOIN organizations_users ON organizations_users.user_id = users.id
) WHERE rownum <= 25

Des suggestions s'il vous plaît?

26
user43685

La projection d'une requête ne peut avoir qu'une seule instance d'un nom donné. Comme le montre votre clause WHERE, vous disposez de plusieurs tables avec une colonne appelée ID. Comme vous sélectionnez *, votre projection comportera plusieurs colonnes appelées ID. Sinon, le compilateur aurait lancé ORA-00918.

La solution est assez simple: vous devrez développer la projection pour sélectionner explicitement les colonnes nommées. Ensuite, vous pouvez omettre les colonnes dupliquées en conservant (par exemple) COACHES.ID ou utiliser des alias de colonne: coaches.id as COACHES_ID.

Cela vous semble peut-être beaucoup de dactylographie, mais c'est le seul moyen. Si cela vous convient, SELECT * est considéré comme une mauvaise pratique dans le code de production: les colonnes nommées explicitement sont beaucoup plus sûres. 

45
APC

Vous avez plusieurs colonnes nommées la même chose dans votre requête interne, donc l'erreur est générée dans la requête externe. Si vous vous débarrassez de la requête externe, elle devrait être exécutée, même si elle reste confuse:

SELECT DISTINCT
    coaches.id,
    people.*,
    users.*,
    coaches.*
FROM "COACHES"
    INNER JOIN people ON people.id = coaches.person_id
    INNER JOIN users ON coaches.person_id = users.person_id
    LEFT OUTER JOIN organizations_users ON organizations_users.user_id = users.id
WHERE
    rownum <= 25

Il serait beaucoup meilleur (pour la lisibilité et la performance) de spécifier exactement les champs dont vous avez besoin dans chacune des tables au lieu de les sélectionner tous de toute façon. Ensuite, si vous avez vraiment besoin de deux champs appelés la même chose provenant de tables différentes, utilisez des alias de colonnes pour les différencier. 

8
Craig

Vous pouvez également voir cette erreur lors de la sélection d'une union où les colonnes correspondantes peuvent être nulles. 

select * from (select D.dept_no, D.nullable_comment
                  from dept D
       union
               select R.dept_no, NULL
                 from redundant_dept R
)

Cela confond apparemment l’analyseur. Une solution consiste à attribuer un alias de colonne à la colonne toujours nulle.

select * from (select D.dept_no, D.comment
                  from dept D
       union
               select R.dept_no, NULL "nullable_comment"
                 from redundant_dept R
)

L'alias ne doit pas nécessairement être identique à la colonne correspondante, mais l'en-tête de colonne dans le résultat dépend de la première requête parmi les membres de l'union. Il s'agit donc probablement d'une bonne pratique.

0
C Payne