2009-11-25 7 views
4

им с небольшой проблемой синтаксиса в моем запросе (упрощенный):Oracle Join Using + подзапросы: ORA-00904 строка: неверный идентификатор

select * 
from table1 t1 
inner join table2 t2 using (pk1) 
inner join table3 t3 using (pk2) 
where not exists (select1 from table4 t4 where t4.pk1 = t1.pk1) 

С помощью «используя» ключевое слово, оракул оленьей кожи позволяет идентификатор таблицы в перед именем столбца (например: t1.pk1, только pk1 могут быть использованы)

Если я пишу:

select * 
from table1 t1 
inner join table2 t2 using (pk1) 
inner join table3 t3 using (pk2) 
where not exists (select1 from table4 t4 where t4.pk1 = pk1) 

Этот запрос не даст ожидаемых результатов.

Но так как я использую подзапрос «существует», как я могу присоединиться к этому подзапросу?

Конечно, я полагаю, что я мог бы написать этот запрос другим способом и избежать существующего, или я НЕ мог использовать «использование».

Но возможно ли «соединение/использование» в сочетании с подзапросом в предложении where?

Edit: с помощью Oracle 10gR2

ответ

3

Интересная проблема! Лучшее, что я могу управлять, при этом используя ИСПОЛЬЗОВАНИЕ является:

select * from 
(select * 
    from table1 t1 
    inner join table2 t2 using (pk1) 
    inner join table3 t3 using (pk2) 
) v 
where not exists (select1 from table4 t4 where t4.pk1 = v.pk1) 
+0

Действительно, это единственный способ сделать это, не уклоняясь ИСПОЛЬЗОВАНИЕМ полностью (лично я предпочитаю придерживаться JOIN..ON, а не использовать). –

1

Вы не можете использовать определители таблицы с естественными соединениями.

Этот запрос:

select 1 from table4 t4 where t4.pk1 = pk1 

в настоящее время анализируется как

select 1 from table4 t4 where t4.pk1 = t4.pk1 

и NOT EXISTS над ней всегда возвращает ложь, если есть только одна запись в table4.

Просто используйте явные JOIN условия:

WITH table1 AS 
     (
     SELECT 1 AS pk1 
     FROM dual 
     ), 
     table2 AS 
     (
     SELECT 1 AS pk1, 1 AS pk2 
     FROM dual 
     ), 
     table3 AS 
     (
     SELECT 1 AS pk2 
     FROM dual 
     ), 
     table4 AS 
     (
     SELECT 2 AS pk1 
     FROM dual 
     ) 
SELECT * 
FROM table1 t1 
JOIN table2 t2 
ON  t2.pk1 = t1.pk1 
JOIN table3 t3 
ON  t3.pk2 = t2.pk2 
WHERE NOT EXISTS 
     (
     SELECT 1 
     FROM table4 t4 
     WHERE t4.pk1 = t1.pk1 
     )