我想知道以下奇怪的行为。
此函数应将所选数据记录到表undefined
(此表为空):
spring.datasource.initialize=true
spring.datasource.url=jdbc:h2:~/test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MV_STORE=FALSE;MVCC=FALSE
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=true
测试a)
使用以下select语句的测试成功(如预期):
ps_cs_corr_data_tb
选择结果:
create or replace function cs_corr_data(i_id in varchar2,
i_key1 in varchar2,
i_key2 in varchar2,
i_key3 in varchar2,
i_key4 in varchar2,
i_key5 in varchar2)
return number as pragma autonomous_transaction;
begin
insert into ps_cs_corr_data_tb
(descr,
cs_key_id_01,
cs_key_id_02,
cs_key_id_03,
cs_key_id_04,
cs_key_id_05)
values
(i_id, i_key1, i_key2, i_key3, i_key4, i_key5);
commit;
return 1; /* insert successful */
exception
when dup_val_on_index then
return 0;
end;
导致记录表:
select b.id, b.key1, b.key2, b.key3, b.key4, b.key5
from (select a.id, a.key1, a.key2, a.key3, a.key4, a.key5
from ( -- test data
select '1' as id,'1' as key1,' ' as key2,' ' as key3,' ' as key4,' ' as key5 from dual union all
select '1' as id,'2' as key1,' ' as key2,' ' as key3,' ' as key4,' ' as key5 from dual union all
select '1' as id,'3' as key1,' ' as key2,' ' as key3,' ' as key4,' ' as key5 from dual union all
select '1' as id,'4' as key1,' ' as key2,' ' as key3,' ' as key4,' ' as key5 from dual union all
select '1' as id,'5' as key1,' ' as key2,' ' as key3,' ' as key4,' ' as key5 from dual
) a
-- some conditions
where a.id = '1'
and a.key1 = '4') b
-- log the results of selection
where cs_corr_data(b.id, b.key1, b.key2, b.key3, b.key4, b.key5) = 1;
到目前为止预期的结果!
解释计划:
ID KEY1 KEY2 KEY3 KEY4 KEY5
1 4
测试b)
现在使用不同的测试数据准备相同的测试(但是相同的测试数据):
select * from ps_cs_corr_data_tb d;
DESCR CS_KEY_ID_01 CS_KEY_ID_02 CS_KEY_ID_03 CS_KEY_ID_04 CS_KEY_ID_05
1 4
选择结果:
Plan hash value: 334628103
-------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 90 | 2 (0)| 00:00:01 |
| 1 | VIEW | | 5 | 90 | 2 (0)| 00:00:01 |
| 2 | UNION-ALL | | | | | |
|* 3 | FILTER | | | | | |
| 4 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
|* 5 | FILTER | | | | | |
| 6 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
|* 7 | FILTER | | | | | |
| 8 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
|* 9 | FILTER | | | | | |
| 10 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
|* 11 | FILTER | | | | | |
| 12 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
-------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter(NULL IS NOT NULL AND "CS_CORR_DATA"('1','1',' ',' ',' ','
')=1)
5 - filter(NULL IS NOT NULL AND "CS_CORR_DATA"('1','2',' ',' ',' ','
')=1)
7 - filter(NULL IS NOT NULL AND "CS_CORR_DATA"('1','3',' ',' ',' ','
')=1)
9 - filter("CS_CORR_DATA"('1','4',' ',' ',' ',' ')=1)
11 - filter(NULL IS NOT NULL AND "CS_CORR_DATA"('1','5',' ',' ',' ','
')=1)
导致记录表:
select b.id, b.key1, b.key2, b.key3, b.key4, b.key5
from (select a.id, a.key1, a.key2, a.key3, a.key4, a.key5
from (select '1' as id,
to_char(level) as key1,
' ' as key2,
' ' as key3,
' ' as key4,
' ' as key5
from dual
connect by level <= 5) a
where a.id = '1'
and a.key1 = '4') b
where cs_corr_data(b.id, b.key1, b.key2, b.key3, b.key4, b.key5) = 1;
解释计划:
ID KEY1 KEY2 KEY3 KEY4 KEY5
1 4
有什么想法在这里发生了什么?
答案 0 :(得分:2)
Oracle(以及任何关系数据库)可以自由地以任何预期最有效的顺序评估谓词。在任一查询中,可以首先自由地评估函数谓词,或者首先评估a.id = '1' and a.key1 = '4'
谓词,或者评估这两个谓词之间的函数谓词。看来优化器在第二种情况下(至少这次)选择的实际计划是在第一种情况下选择评估函数时首先评估函数。当然,优化器可以在两种情况下明天改变主意,因此您不应该依赖于特定的查询计划。