天天看點

【SQL 學習】表連接配接--natural join 的一個bug

自然連接配接(NATURAL JOIN)是一種特殊的等價連接配接,它将表中具有相同名稱的列自動進行記錄比對。自然連接配接不必指定任何同等連接配接條件。這篇文章講的一個關于natural join 的bug!(由 dingjun123 提示!)

SQL> conn store/yang

已連接配接。

SQL> create table a as select * from all_objects;

表已建立。

SQL> set timing on

SQL> create table b as select * from all_objects;

已用時間:  00: 00: 20.36

SQL> set autot on

SQL> set linesize 100

SQL> select count(*) from a natural join b;

  COUNT(*)                                                                                         

----------                                                                                         

         0         ---錯誤的結果!                                                                                

已用時間:  00: 00: 00.04

執行計劃

----------------------------------------------------------

Plan hash value: 1397777030 

------------------------------------------------------------------------------------

| Id  | Operation           | Name | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |

------------------------------------------------------------------------------------               

|   0 | SELECT STATEMENT    |      |     1 |   316 |       |  1500   (1)| 00:00:18 |

|   1 |  SORT AGGREGATE     |      |     1 |   316 |       |            |          |

|*  2 |   HASH JOIN         |      |     1 |   316 |  8184K|  1500   (1)| 00:00:18 |

|   3 |    TABLE ACCESS FULL| A    | 49280 |  7603K|       |   281   (1)| 00:00:04 |

|   4 |    TABLE ACCESS FULL| B    | 66983 |    10M|       |   282   (1)| 00:00:04 |

Predicate Information (identified by operation id):                                                

---------------------------------------------------                                                

   2 - access("A"."EDITION_NAME"="B"."EDITION_NAME" AND                                            

              "A"."NAMESPACE"="B"."NAMESPACE" AND "A"."SECONDARY"="B"."SECONDARY" AND

              "A"."GENERATED"="B"."GENERATED" AND "A"."TEMPORARY"="B"."TEMPORARY" AND

              "A"."STATUS"="B"."STATUS" AND "A"."TIMESTAMP"="B"."TIMESTAMP" AND

              "A"."LAST_DDL_TIME"="B"."LAST_DDL_TIME" AND "A"."CREATED"="B"."CREATED" AND

              "A"."OBJECT_TYPE"="B"."OBJECT_TYPE" AND

              "A"."DATA_OBJECT_ID"="B"."DATA_OBJECT_ID" AND

              "A"."OBJECT_ID"="B"."OBJECT_ID" AND "A"."SUBOBJECT_NAME"="B"."SUBOBJECT_NAME

              " AND "A"."OBJECT_NAME"="B"."OBJECT_NAME" AND "A"."OWNER"="B"."OWNER")

Note      

-----

   - dynamic sampling used for this statement                                                      

統計資訊

------------------------------------------------------

       1801  recursive calls

          0  db block gets

       1407  consistent gets

          0  physical reads

          0  redo size

        418  bytes sent via SQL*Net to client

        416  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

         17  sorts (memory)    

          0  sorts (disk)   

          1  rows processed

SQL> set autot off

SQL> truncate table a;

表被截斷。

已用時間:  00: 00: 00.43

SQL> truncate table b;

SQL> drop table a;

表已删除。

已用時間:  00: 00: 00.57

SQL> drop table b;

已用時間:  00: 00: 00.06

SQL> create table a (id number ,name varchar2(10)) ;

已用時間:  00: 00: 00.10

SQL> insert into a values (1,'aa');

已建立 1 行。

已用時間:  00: 00: 00.00

SQL> insert into a values (2,'bb');

SQL> create table b as select * from a ;

已用時間:  00: 00: 00.29

         2      ----結果是正确的 

 已用時間:  00: 00: 00.03

----------------------------------------------------------                                         

Plan hash value: 1397777030                                                                        

----------------------------------------------------------------------------                       

| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |

|   0 | SELECT STATEMENT    |      |     1 |    40 |     7  (15)| 00:00:01 |

|   1 |  SORT AGGREGATE     |      |     1 |    40 |            |          |

|*  2 |   HASH JOIN         |      |     1 |    40 |     7  (15)| 00:00:01 |

|   3 |    TABLE ACCESS FULL| A    |     2 |    40 |     3   (0)| 00:00:01 |

|   4 |    TABLE ACCESS FULL| B    |     2 |    40 |     3   (0)| 00:00:01 |

Predicate Information (identified by operation id):

--------------------------------------------------

   2 - access("A"."NAME"="B"."NAME" AND "A"."ID"="B"."ID")

Note                         

-----            

   - dynamic sampling used for this statement

        103  recursive calls

         34  consistent gets

          5  physical reads

          0  redo size 

        419  bytes sent via SQL*Net to client

          4  sorts (memory)

          0  sorts (disk)

已用時間:  00: 00: 00.25

已用時間:  00: 00: 00.01

已用時間:  00: 00: 00.28

SQL> create table b as select * from all_objects where rownum 表已建立。

已用時間:  00: 00: 00.87

已用時間:  00: 00: 00.35

SQL> create table a  as select * from b; a和b 兩個表是一樣的。

SQL> select * from a

  2  minus

  3  select * from b;

未標明行

已用時間:  00: 00: 00.03

SQL> select count(*) from a;

       999                                                                                         

SQL> select count(*) from b;

         0   ---應該傳回999行,但是結果是0 顯然這是一個bug                                                                                      

----------------------------------------------------------------------------

|   0 | SELECT STATEMENT    |      |     1 |   316 |    13   (8)| 00:00:01 |

|   1 |  SORT AGGREGATE     |      |     1 |   316 |            |          |

|*  2 |   HASH JOIN         |      |     1 |   316 |    13   (8)| 00:00:01 |

|   3 |    TABLE ACCESS FULL| A    |   999 |   154K|     6   (0)| 00:00:01 |

|   4 |    TABLE ACCESS FULL| B    |   999 |   154K|     6   (0)| 00:00:01 |

---------------------------------------------------

   2 - access("A"."EDITION_NAME"="B"."EDITION_NAME" AND

              "A"."LAST_DDL_TIME"="B"."LAST_DDL_TIME" AND "A"."CREATED"="B"."CREATED"

              AND "A"."OBJECT_TYPE"="B"."OBJECT_TYPE" AND

              "A"."OBJECT_ID"="B"."OBJECT_ID" AND 

              "A"."SUBOBJECT_NAME"="B"."SUBOBJECT_NAME" AND

              "A"."OBJECT_NAME"="B"."OBJECT_NAME" AND "A"."OWNER"="B"."OWNER")

Note                                                                                               

-----     

        582  recursive calls

        168  consistent gets

          6  sorts (memory)       

SQL> conn scott/yang

SQL> select ename ,dname from emp natural join dept;

ENAME      DNAME     

---------- -----------

CLARK      ACCOUNTING

KING       ACCOUNTING

MILLER     ACCOUNTING

JONES      RESEARCH

FORD       RESEARCH

ADAMS      RESEARCH

SMITH      RESEARCH                                                                                

SCOTT      RESEARCH

WARD       SALES

TURNER     SALES

ALLEN      SALES

JAMES      SALES

BLAKE      SALES

MARTIN     SALES

-------結果是正确的!

已選擇14行。

Plan hash value: 844388907                                                                         

----------------------------------------------------------------------------------------

| Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Time     |

----------------------------------------------------------------------------------------           

|   0 | SELECT STATEMENT             |         |    14 |   308 |     6  (17)| 00:00:01 |

|   1 |  MERGE JOIN                  |         |    14 |   308 |     6  (17)| 00:00:01 |

|   2 |   TABLE ACCESS BY INDEX ROWID| DEPT    |     4 |    52 |     2   (0)| 00:00:01 |

|   3 |    INDEX FULL SCAN           | PK_DEPT |     4 |       |     1   (0)| 00:00:01 |

|*  4 |   SORT JOIN                  |         |    14 |   126 |     4  (25)| 00:00:01 |

|   5 |    TABLE ACCESS FULL         | EMP     |    14 |   126 |     3   (0)| 00:00:01 |

Predicate Information (identified by operation id):  

   4 - access("EMP"."DEPTNO"="DEPT"."DEPTNO")

       filter("EMP"."DEPTNO"="DEPT"."DEPTNO")

          0  recursive calls

         11  consistent gets

          0  physical reads 

          0  redo size  

        674  bytes sent via SQL*Net to client

          2  SQL*Net roundtrips to/from client                                                     

          1  sorts (memory)

         14  rows processed

---貼出執行計劃,隻是想看看 natural join 會走什麼樣的計劃。

重點是這個對于all_objects 構造出的表使用natural join 查詢時 沒有給出正确的結果。。