我执行了一个SQL语句并遇到了麻烦。我无法理解这个输出是如何产生的。 我的员工表是:Emp_Id是主键,dept_no是其他表的外键。
EMP_ID EMP_NAME DEPT_NO MGR_NAME MGR_NO
---------- -------------------- ---------- ---------- -----------
111 Anish 121 Tanuj 1123
112 Aman 122 Jasmeet 1234
1123 Tanuj 122 Vipul 122
1234 Jasmeet 122 Anish 111
122 Vipul 123 Aman 112
100 Chetan 123 Anoop 666
101 Antal Aman
1011 Anjali 126
1111 Angelina 127
我的dep1表是:
DEPT_ID DEPT_NAME
---------- -------------
121 CSE
122 ECE
123 MEC
这两张表根本没有关联。
SQL查询是:
SQL> select emp_name
from employee
where dept_no IN (select dept_no from dep1 where dept_name='MEC');
输出是:
EMP_NAME
--------------------
Anish
Aman
Tanuj
Jasmeet
Vipul
Chetan
Anjali
Angelina
8 rows selected.
如果我将where条件更改为dept_name ='me',则不返回任何行。 有人可以解释为什么执行没有产生错误,因为dept_no不是dep1表的列。以及如何生成输出。
答案 0 :(得分:0)
从您的查询开始,
..where dept_no IN (select dept_no ...); -- it is similar as using EXISTS
条件EXISTS
在这里完成:( oracle不会为EXISTS子句返回错误。)
CREATE TABLE my_test(ID INT);
CREATE TABLE my_new_test ( new_ID INT);
EXPLAIN PLAN FOR
select * from my_test where id in( select id from my_new_test);
select * from table(dbms_xplan.display);
-----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 4 (0)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS FULL | MY_TEST | 1 | 13 | 2 (0)| 00:00:01 |
|* 3 | FILTER | | | | | |
| 4 | TABLE ACCESS FULL| MY_NEW_TEST | 1 | | 2 (0)| 00:00:01 |
-----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter( EXISTS (SELECT 0 FROM "MY_NEW_TEST" "MY_NEW_TEST" WHERE
:B1=:B2))
3 - filter(:B1=:B2)
Note
-----
- dynamic sampling used for this statement (level=2)
如果您执行有效列的计划,请在此处(new_id): 然后进行正常访问:
1 - ACCESS("ID"="NEW_ID")
以下将导致错误:
EXPLAIN PLAN FOR
select * from my_test where id in( select some_thing from my_new_test);
SQL Error: ORA-00904: "SOME_THING": invalid identifier
答案 1 :(得分:0)
如果您运行此查询:
select emp_name
from employee
where dept_no IN (select t.dept_no from dep1 t where dept_name='MEC');
你会在你的查询中看到错误dept_no来自employee表(不是来自dep1表),当dept_no为null时,没有结果将从它返回,如果你将dept_name更改为不在dep1表很清楚你的dep1表什么都没有返回,然后dept_no就什么都不能。
答案 2 :(得分:0)
让我试着回答一下。
Oracle使用优化程序来决定解释计划。 Oracle可能会根据需要重写您的查询,并认为哪个更好。并且存在和可存在是可互换的,性能取决于不同的东西。 (存在以全表扫描和使用索引结束)。
让我谈谈你的情况。以下是您的查询的解释计划
Plan hash value: 3333342911
----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 9 | 225 | 6 (0)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS FULL | EMPLOYEE | 9 | 225 | 3 (0)| 00:00:01 |
|* 3 | FILTER | | | | | |
|* 4 | TABLE ACCESS FULL| DEPARTMENT | 1 | 12 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter( EXISTS (SELECT 0 FROM "DEPARTMENT" "DEPARTMENT" WHERE
:B1=:B2 AND "DEPT_NAME"='MEC'))
3 - filter(:B1=:B2)
4 - filter("DEPT_NAME"='MEC')
Note
-----
- dynamic sampling used for this statement (level=2)
此解释计划清楚地表明查询被重写为使用存在,它等同于
select emp_name from employee where exists (select 0 from department where dept_name = 'MEC' and dept_no = dept_no);
上述查询是一个有效的查询,您将获得正确的结果。
绑定变量只不过是dept_no(连接列)。
请参阅此IN vs EXISTS in oracle链接,了解有关in和exists的更多信息。
如果使用正确的列名,则说明计划完全不同。以下是查询和解释计划
查询:
select emp_name from employee where dept_no IN (select dept_id from department where dept_name='MEC');
解释计划:
Plan hash value: 3817251802
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 100 | 7 (15)| 00:00:01 |
|* 1 | HASH JOIN SEMI | | 2 | 100 | 7 (15)| 00:00:01 |
| 2 | TABLE ACCESS FULL| EMPLOYEE | 9 | 225 | 3 (0)| 00:00:01 |
|* 3 | TABLE ACCESS FULL| DEPARTMENT | 1 | 25 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("DEPT_NO"="DEPT_ID")
3 - filter("DEPT_NAME"='MEC')
Note
-----
- dynamic sampling used for this statement (level=2)
Oracle认为最好使用过滤器和散列连接来获取所需的详细信息。
此行为取决于oracle查询解析器和优化程序。
答案 3 :(得分:-1)
加入怎么样?
select a.emp_name
from employee a
join dep1 b
on a.dept_no = b.dept_id
where b.dept_name = 'MEC'