查詢與插入資料使用rownum與level

skyin_1603發表於2016-10-23
rownum與level在某些場景的用法是一樣的,但在某些場景就產生天淵之別的結果,提醒大家平時慎用level。
以下是兩者一些場景中使用的比較:

----rownum 與level的用法:
--例子:
題目:列印2016-06-15~2016-07-14之間的連續日期。

--使用rownum查詢:
SQL> select (to_date('2016-06-15','yyyy-mm-dd') + rownum-1) service_date
  2  from dual
  3  connect by rownum <= (to_date('2016-07-14','yyyy-mm-dd') -
  4  to_date('2016-06-15','yyyy-mm-dd')+1);

SERVICE_DATE
-------------------
2016-06-15 00:00:00
2016-06-16 00:00:00
2016-06-17 00:00:00
2016-06-18 00:00:00
... ...
2016-07-12 00:00:00
2016-07-13 00:00:00
2016-07-14 00:00:00
30 rows selected.

--level查詢:
SQL> select (to_date('2016-06-15','yyyy-mm-dd') + level-1) service_date
  2  from dual
  3  connect by level <= (to_date('2016-07-14','yyyy-mm-dd') -
  4  to_date('2016-06-15','yyyy-mm-dd')+1);

SERVICE_DATE
-------------------
2016-06-15 00:00:00
2016-06-16 00:00:00
2016-06-17 00:00:00
2016-06-18 00:00:00
2016-06-19 00:00:00
2016-06-20 00:00:00
2016-06-21 00:00:00
... ...
2016-07-12 00:00:00
2016-07-13 00:00:00
2016-07-14 00:00:00
30 rows selected.
以上兩種結果是一樣的。

--分解檢視:
SQL> select sysdate from dual;
SYSDATE
-------------------
2016-10-21 18:44:06

SQL> select (sysdate + rownum) from dual;
(SYSDATE+ROWNUM)
-------------------
2016-10-22 18:46:11

SQL> select (sysdate + rownum-1) from dual
(SYSDATE+ROWNUM-1)
-------------------
2016-10-21 18:46:40

--使用level檢視:
SQL> select (sysdate + level-1) from dual connect by level<=5;
(SYSDATE+LEVEL-1)
-------------------
2016-10-21 18:50:46
2016-10-22 18:50:46
2016-10-23 18:50:46
2016-10-24 18:50:46
2016-10-25 18:50:46

SQL> select (sysdate +level) from dual connect by level<=5;

(SYSDATE+LEVEL)
-------------------
2016-10-22 18:51:10
2016-10-23 18:51:10
2016-10-24 18:51:10
2016-10-25 18:51:10
2016-10-26 18:51:10

SQL> select (sysdate + rownum) from dual connect by rownum <=5;
(SYSDATE+ROWNUM)
-------------------
2016-10-22 18:52:02
2016-10-23 18:52:02
2016-10-24 18:52:02
2016-10-25 18:52:02
2016-10-26 18:52:02

--使用兩個分別查詢emp表(表中有14條資料):
--使用level查詢emp表:
SQL> col rownum for 99;
SQL> select rownum,empno,ename,job from emp
  2  where rownum <=10;

ROWNUM      EMPNO ENAME      JOB
------ ---------- ---------- ---------
     1       7369 SMITH      CLERK
     2       7499 ALLEN      SALESMAN
     3       7521 WARD       SALESMAN
     4       7566 JONES      MANAGER
  ... ...
     9       7839 KING       PRESIDENT
    10       7844 TURNER     SALESMAN
10 rows selected.

SQL> select empno,ename,job from emp
  2  connect by level<=2;
     EMPNO ENAME      JOB
---------- ---------- ---------
      7369 SMITH      CLERK
      7369 SMITH      CLERK
      7499 ALLEN      SALESMAN
      7521 WARD       SALESMAN
      7566 JONES      MANAGER
      7654 MARTIN     SALESMAN
      7698 BLAKE      MANAGER
      7782 CLARK      MANAGER
      7788 SCOTT      ANALYST
      7839 KING       PRESIDENT
      7844 TURNER     SALESMAN
      ... ...
           EMPNO ENAME      JOB
---------- ---------- ---------
      7934 MILLER     CLERK
210 rows selected.
可以看到兩者的產生的結果是不一樣的。

--使用兩者往測試空表中插入資料:
--使用rownum
SQL> create table t7(id number(2),created date);
Table created.

--使用rownum進行插入:
SQL> insert into t7 select * from t6 where rownum <=5;
5 rows created.

--檢視錶t7的資料:
SQL> select * from t7;
        ID CREATED
---------- ---------
         1 21-OCT-16
         2 21-OCT-16
         3 21-OCT-16
         4 21-OCT-16
         5 21-OCT-16

--使用level:
SQL> insert into t7 select * from t6
  2   connect by level <=2;
156 rows created.

--檢視錶t7的資料:
SQL> select * from t7 order by 1;
        ID CREATED
---------- -------------------
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
... ...
SQL> insert into t7 select * from t6
  2   connect by level <=2;
156 rows created.

--檢視錶t7的資料:
SQL> select * from t7 order by 1;
        ID CREATED
---------- -------------------
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
... ...
        ID CREATED
---------- -------------------
        12 2016-10-21 19:02:56
        12 2016-10-21 19:02:56
156 rows selected.


--建立表t8測試表:(t7中有4條記錄)
SQL> insert into t8 select * from t7
  2  connect by level <=3;
84 rows created.

--檢視錶t8的資料:
SQL> select * from t8 order by 1;
        ID CREATED
---------- -------------------
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
        ID CREATED
---------- -------------------
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         1 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
        ID CREATED
---------- -------------------
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
        ID CREATED
---------- -------------------
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
         2 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
        ID CREATED
---------- -------------------
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
        ID CREATED
---------- -------------------
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
         3 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
        ID CREATED
---------- -------------------
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
        ID CREATED
---------- -------------------
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
         4 2016-10-21 19:02:56
84 rows selected.

從以上的測試過程中發現level其實就是層級、乘方的意思。就拿往空表t8中插入資料來說,表t7中有4條記錄,
我們利用表t7的資料查到表t8中,我們執行SQL> insert into t8 select * from t7 connect by level <=3;
最後發現出入了84行:
以下是模擬插入的過程:
----------第一:0+4*1=4;
----------第二:4+4*4=20
----------第三:4+4*4+4*4*4=84。
總和就是84行,就是這樣理解level就可以了。

也即:connect by level<=N, (level一定要與connect by一起用,但rownum可以獨立用)
假設原表有X條資料,這樣查詢使用就是:connect by level<=N就是:
X+X*X+X*X*X*X+X*X*X*X*X+X...N個X相乘的結果,資料量大的話,查詢就花銷很多記憶體。
所以沒必要是,寧願使用rownum都不要使用level用來給測試表插入資料。










來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31392094/viewspace-2126956/,如需轉載,請註明出處,否則將追究法律責任。

相關文章