subselect的事务行为

时间:2016-10-04 13:54:07

标签: oracle

我想知道以下奇怪的行为。

此函数应将所选数据记录到表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                

有什么想法在这里发生了什么?

1 个答案:

答案 0 :(得分:2)

Oracle(以及任何关系数据库)可以自由地以任何预期最有效的顺序评估谓词。在任一查询中,可以首先自由地评估函数谓词,或者首先评估a.id = '1' and a.key1 = '4'谓词,或者评估这两个谓词之间的函数谓词。看来优化器在第二种情况下(至少这次)选择的实际计划是在第一种情况下选择评估函数时首先评估函数。当然,优化器可以在两种情况下明天改变主意,因此您不应该依赖于特定的查询计划。