Tom新書的一個小bug——mystat指令碼

yangtingkun發表於2008-03-21

今天在看Tom的新書Oracle9i&10g程式設計藝術發現了一個小問題。

 

 

Tom在這本書開頭部分介紹了他自己的常用工具,其中包括mystat指令碼。這個指令碼的目的是獲取一個操作的某個統計結果變化情況。

其中由兩個指令碼構成,mystat記錄狀態的初始狀態,mystat2記錄最終狀態,並顯示差異。

書中給出的mystat指令碼如下:

SET ECHO OFF
SET VERIFY OFF
COLUMN VALUE NEW_VAL V
DEFINE S="&1"
SET AUTOTRACE OFF
SELECT A.NAME, B.VALUE
FROM V$STATNAME A, V$MYSTAT B
WHERE A.STATISTIC# = B.STATISTIC#
AND LOWER(A.NAME) LIKE '%' || LOWER('&S') || '%'
/
SET ECHO ON

另一個指令碼mystat2如下:

SET ECHO OFF
SET VERIFY OFF
SELECT A.NAME, B.VALUE V, TO_CHAR(B.VALUE - &V, '999,999,999,999') DIFF
FROM V$STATNAME A, V$MYSTAT B
WHERE A.STATISTIC# = B.STATISTIC#
AND LOWER(A.NAME) LIKE '%' || LOWER('&S') || '%'
/
SET ECHO ON

看一下這兩個指令碼的使用:

SQL> @e:\mystat "undo change vector size"
SQL> SET ECHO OFF

NAME                                VALUE
------------------------------ ----------
undo change vector size                 0

SQL> delete t;

已刪除4行。

SQL> @e:\mystat2
SQL> SET ECHO OFF

NAME                                    V DIFF
------------------------------ ---------- ----------------
undo change vector size              1592            1,592

書中給出的例子沒有任何的問題,但是指令碼本身存在問題。

由於Tom使用了SQLPLUSNEW_VALUE功能來獲取前後兩次統計結果的差異,因此這個功能僅對單個統計項有效。

但是Tom給出的指令碼中在輸入的統計項兩邊追加了%,使得統計項可以模糊匹配,這雖然方便了查詢輸入,但是很容易造成輸入的關鍵字匹配多個統計項。而一旦出現這種情況,則MYSTAT2指令碼中的差異統計就會完全錯誤:

SQL> @e:\mystat "redo"
SQL> SET ECHO OFF

NAME                                VALUE
------------------------------ ----------
redo synch writes                       1
redo synch time                         1
redo blocks read for recovery           0
redo entries                            6
redo size                            4152
redo buffer allocation retries          0
redo wastage                            0
redo writer latching time               0
redo writes                             0
redo blocks written                     0
redo write time                         0
redo log space requests                 0
redo log space wait time                0
redo log switch interrupts              0
redo ordering marks                     0
redo subscn max counts                  0
IMU Redo allocation size             1248

已選擇17行。

SQL> create table t_redo as select * from dba_objects;

表已建立。

SQL> @e:\mystat2
SQL> SET ECHO OFF

NAME                                    V DIFF
------------------------------ ---------- ----------------
redo synch writes                       3           -1,245
redo synch time                         1           -1,247
redo blocks read for recovery           0           -1,248
redo entries                         1223              -25
redo size                         5817596        5,816,348
redo buffer allocation retries          0           -1,248
redo wastage                            0           -1,248
redo writer latching time               0           -1,248
redo writes                             0           -1,248
redo blocks written                     0           -1,248
redo write time                         0           -1,248
redo log space requests                 0           -1,248
redo log space wait time                0           -1,248
redo log switch interrupts              0           -1,248
redo ordering marks                    20           -1,228
redo subscn max counts                  0           -1,248
IMU Redo allocation size             1248                0

已選擇17行。

這個結果已經很清晰的說明了問題,因此這裡應該將指令碼從LIKE方式改為等於的方式,這樣可以避免錯誤的發生。

 

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

相關文章