最近我修复了一些错误:连接条件中有rownum。
像这样:在 t1.id=t2.id 和 rownum<2 上左连接 t1。因此,无论“左连接”如何,它都应该只返回一行。
当我进一步研究这一点时,我意识到我不明白 Oracle 如何在“左连接”条件下评估 rownum。让我们创建两个示例表:主表和明细表。
create table MASTER
(
ID NUMBER not null,
NAME VARCHAR2(100)
)
;
alter table MASTER
add constraint PK_MASTER primary key (ID);
prompt Creating DETAIL...
create table DETAIL
(
ID NUMBER not null,
REF_MASTER_ID NUMBER,
NAME VARCHAR2(100)
)
;
alter table DETAIL
add constraint PK_DETAIL primary key (ID);
alter table DETAIL
add constraint FK_DETAIL_MASTER foreign key (REF_MASTER_ID)
references MASTER (ID);
prompt Disabling foreign key constraints for DETAIL...
alter table DETAIL disable constraint FK_DETAIL_MASTER;
prompt Loading MASTER...
insert into MASTER (ID, NAME)
values (1, 'First');
insert into MASTER (ID, NAME)
values (2, 'Second');
commit;
prompt 2 records loaded
prompt Loading DETAIL...
insert into DETAIL (ID, REF_MASTER_ID, NAME)
values (1, 1, 'REF_FIRST1');
insert into DETAIL (ID, REF_MASTER_ID, NAME)
values (2, 1, 'REF_FIRST2');
insert into DETAIL (ID, REF_MASTER_ID, NAME)
values (3, 1, 'REF_FIRST3');
commit;
prompt 3 records loaded
prompt Enabling foreign key constraints for DETAIL...
alter table DETAIL enable constraint FK_DETAIL_MASTER;
set feedback on
set define on
prompt Done.
然后我们有这个查询:
select * from master t
left join detail d on d.ref_master_id=t.id
结果集是可预测的:我们有来自主表的所有行和来自明细表的 3 行匹配这个条件 d.ref_master_id=t.id。
然后我将“rownum = 1”添加到连接条件中,结果是一样的
select * from master t
left join detail d on d.ref_master_id=t.id and rownum=1
最有趣的是我设置了“rownum<-666”,又得到了同样的结果!
select * from master t
left join detail d on d.ref_master_id=t.id and rownum<-666.
由于结果集的原因,我们可以说对于明细表中的 3 行,此条件被评估为“真”。但如果我使用“内部连接”,一切都会按预期进行。
select * from master t
join detail d on d.ref_master_id=t.id and rownum<-666.
此查询不返回任何行,因为我无法想象 rownum 小于 -666 :-)
此外,如果我使用 oracle 语法进行外连接,使用“(+)”也一切顺利。
select * from master m ,detail t
where m.id=t.ref_master_id(+) and rownum<-666.
此查询也不返回任何行。
谁能告诉我,我对外部联接和 rownum 有什么误解?