web-dev-qa-db-ja.com

ORA-00918:SELECTで列が曖昧に定義されています*

ORA-00918の取得:列があいまいに定義されています:この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

何か提案はありますか?

27
user43685

クエリのプロジェクションには、特定の名前のインスタンスを1つだけ含めることができます。 WHERE句が示すように、IDという列を持つ複数のテーブルがあります。 *を選択しているため、投影にはIDと呼ばれるいくつかの列があります。あるいは、ORA-00918を投げるコンパイラーのためではなかったでしょう。

解決策は非常に簡単です。名前付き列を明示的に選択するには、プロジェクションを展開する必要があります。次に、(たとえば)COACHES.IDのみを保持する重複列を除外するか、列エイリアスcoaches.id as COACHES_IDを使用します。

おそらくそれは多くのタイピングとしてあなたを襲いますが、それが唯一の方法です。快適であれば、SELECT *は実動コードでは悪い習慣と見なされます。明示的に名前が付けられた列の方がはるかに安全です。

47
APC

内部クエリに同じものという名前の列が複数あるため、外部クエリでエラーが発生します。外側のクエリを削除する場合は、実行する必要がありますが、まだ混乱します。

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

とにかくすべてを選択するのではなく、各テーブルから必要なフィールドを正確に指定すると、much better(読みやすさとパフォーマンスの両方)になります。次に、異なるテーブルから同じものと呼ばれる2つのフィールドが本当に必要な場合は、列エイリアスを使用してそれらを区別します。

9
Craig

また、対応する列がnullになる可能性のある共用​​体を選択するときに、このエラーが表示されることもあります。

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

これは明らかにパーサーを混乱させます。解決策は、常にnullの列に列エイリアスを割り当てることです。

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

エイリアスは対応する列と同じである必要はありませんが、結果の列見出しは、ユニオンメンバーの中から最初のクエリによって駆動されるため、おそらく良い方法です。

1
C Payne