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
何か提案はありますか?
クエリのプロジェクションには、特定の名前のインスタンスを1つだけ含めることができます。 WHERE句が示すように、IDという列を持つ複数のテーブルがあります。 *
を選択しているため、投影にはIDと呼ばれるいくつかの列があります。あるいは、ORA-00918を投げるコンパイラーのためではなかったでしょう。
解決策は非常に簡単です。名前付き列を明示的に選択するには、プロジェクションを展開する必要があります。次に、(たとえば)COACHES.IDのみを保持する重複列を除外するか、列エイリアスcoaches.id as COACHES_ID
を使用します。
おそらくそれは多くのタイピングとしてあなたを襲いますが、それが唯一の方法です。快適であれば、SELECT *
は実動コードでは悪い習慣と見なされます。明示的に名前が付けられた列の方がはるかに安全です。
内部クエリに同じものという名前の列が複数あるため、外部クエリでエラーが発生します。外側のクエリを削除する場合は、実行する必要がありますが、まだ混乱します。
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つのフィールドが本当に必要な場合は、列エイリアスを使用してそれらを区別します。
また、対応する列が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
)
エイリアスは対応する列と同じである必要はありませんが、結果の列見出しは、ユニオンメンバーの中から最初のクエリによって駆動されるため、おそらく良い方法です。