创建的表和进行的查询不是此问题的主要重点,令我困惑的是,为什么第一个查询和第二个查询返回不同的行数
drop table Reserves;
drop table Sailors;
drop table Boats;
create table Sailors (
sid char(1) not null,
sname char(1) not null,
rating int,
age int not null,
primary key (sid)
);
create table Boats (
bid char(1) not null,
bname char(1) not null,
color varchar(5),
primary key (bid)
);
create table Reserves (
sid char(1) not null,
bid char(1) not null,
rdate int not null,
primary key (sid, bid, rdate),
foreign key (sid) references Sailors(sid)
on delete cascade,
foreign key (bid) references Boats(bid)
on delete cascade
);
------------------------------------------------------------------------------
-- Insert values
insert into Sailors values ('1', 'q', 90, 24);
insert into Sailors values ('0', 's', 60, 22);
insert into Sailors values ('2', 'd', 80, 20);
insert into Sailors values ('3', 'w', 70, 18);
insert into Sailors values ('4', 'a', 60, 19);
insert into Sailors values ('5', 'l', 80, 17);
insert into Sailors values ('6', 'o', 90, 18);
insert into Sailors values ('7', 'q', 70, 20);
insert into Sailors values ('8', 'd', 60, 16);
insert into Sailors values ('9', 'i', 80, 22);
insert into Boats values ('0', 'U', 'red');
insert into Boats values ('1', 'P', 'red');
insert into Boats values ('2', 'Q', 'blue');
insert into Boats values ('3', 'C', 'green');
insert into Boats values ('4', 'L', 'blue');
insert into Boats values ('5', 'O', 'blue');
insert into Boats values ('6', 'A', 'red');
insert into Boats values ('7', 'C', 'red');
insert into Boats values ('8', 'Y', 'green');
insert into Boats values ('9', 'N', 'blue');
insert into Reserves values ('0', '0', 3);
insert into Reserves values ('0', '1', 2);
insert into Reserves values ('0', '2', 1);
insert into Reserves values ('0', '2', 3);
insert into Reserves values ('1', '0', 4);
insert into Reserves values ('3', '2', 2);
insert into Reserves values ('4', '0', 3);
insert into Reserves values ('4', '0', 1);
insert into Reserves values ('4', '1', 3);
insert into Reserves values ('4', '6', 4);
insert into Reserves values ('4', '7', 1);
insert into Reserves values ('5', '8', 2);
insert into Reserves values ('5', '9', 2);
insert into Reserves values ('7', '4', 4);
insert into Reserves values ('7', '5', 1);
insert into Reserves values ('8', '3', 2);
insert into Reserves values ('9', '3', 3);
insert into Reserves values ('9', '0', 1);
insert into Reserves values ('9', '6', 1);
insert into Reserves values ('9', '8', 2);
commit;
select *
from Sailors join Boats on color='red' natural left outer join Reserves
where rdate is null;
select sid
from Sailors join Boats on color='red' natural left outer join Reserves
where rdate is null;
我想找到尚未订购所有红船的水手的sid,上面的第一个查询返回我期望的正确行,尽管如此,第二个查询仅返回sid = 2和sid = 6的行,尽管有两个查询都是一样的 sid 2和6的水手是唯一没有预订任何船只的水手。
据我所知,这似乎是Oracle实施中的一个错误natural [...] join
。我将做一些测试,看看它是否也影响内部联接。
代替natural
联接,可以使用语法left|right|inner join USING(...)
并在using
子句中提供列名称的列表。列的列表应该是在连接的两个成员中具有相同名称的所有列的列表。
对您提供的数据进行的非常简单的实验(即使using(sid, bid)
仅对其中的+1),结果与我们在第一个查询中编写的结果相同,但仅using(sid)
在第二个查询中相同。如果任一查询-不管什么选择,无论是*
或sid
-您使用using
的语法,你得到的输出或者您的第一个或第二个查询中相同的行数,这取决于什么你把在using
条款。
因此,Oracle对第二个查询所做的事情是完全错误的。我只能推测,但是我相信Oracle首先查看该SELECT
子句,也许还查看其他子句,以查看它需要从每个表中检索哪些列。(例如,这告诉优化器它可以使用哪些索引,等等。)然后,在此步骤中,Oracle在第二个查询中确定它不需要bid
。然后,当将“自然”联接转换为自己的内部代码时,它不会bid
作为联接列抛出。哪个是错误的-这就是为什么我将此称为“错误”。
重要说明:其他人评论说,这两个查询都是“错误的”,因为它们不能解决您要解决的问题。这可能是完全正确的。我什至没有看你的问题说明;在这里,我正在回答您的问题,无论出现什么问题,该问题都是有效的-这就是为什么两个查询会产生不同数量的行。即使在您的用例中它们是“错误的”,他们也应该从本质上给出“相同”的错误答案,而不是“不同”的错误答案。那是我上面讨论的唯一内容。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句