对于初学数据库的人来说,关联子查询比较容易让人产生迷惑,举个例子,我要在员工表emp中查询哪些人是领导,那肯定的思路是员工id在manager_id这一列中的员工是领导。

为完成这一个查询我写了两个sql语句:

1.select o.name leader from emp o where exists (select * from emp where emp.manager_id=o.employee_id)

2.select o.name leader from emp o where exists (select * from emp where emp.employee_id=o.manager_id)

第一个是正确的,第二个是错误的

为什么会产生这种差异呢?因为关联子查询是以一种循环检查的方式来查询的,也就是外部查询先取一条记录,然后这记录传进内部查询,用内部查询来筛选此条记录,如果符合内部查询的条件,再返回经内部查询执行过的该记录到外部查询中,取相应的字段显示给用户。

第一个sql中:第一条记录比如是本公司最大的领导,所以他的manager_id中没有值,此条记录传进内部查询就会被emp.manager_id=o.employee_id这个条件来筛选,内部表中的manager_id有和此记录的employee_id相匹配的,所以可以确定此人是领导,取此领导的名字显示给用户,其他的记录同理

第二个sql中:第一条记录比如是本公司最大的领导,所以他的manager_id中没有值,此条记录传进内部查询就会被emp.employee_id=o.manager_id这个条件来筛选,内部表中的employee_id有和此记录的manager_id相匹配的(因为该条记录的manager_id为null),所以可以确定此人不是领导,那结果就错了。然后公司最低职位的一名员工记录传进内部查询,此记录肯定有manager_id,假如等于101,按照模式,内部查询根据emp.employee_id=o.manager_id来判断,此时内部表中可以根据manager_id找到与之相等的employee_id=101的记录,并且此条记录是他领导的记录,那么内部查询就会把刚才外部查询传进来的那条记录再返回出去,这样结果肯定也是错的,因为此人竟然成领导了。注意,外部查询传进什么记录,内部查询经筛选之后就返回哪条记录,此例中,内部查询并没有对传进去的记录进行过筛选,所以结果错误

第二个sql导致最高领导不是领导,最低职员却成了领导