oracle中WMSYS.WM_CONCAT函數的版本差異


     昨天在測試的時候發現,開發人員寫的一段程序放在開發庫中是好的,但是放在測試庫中就會有問題。開發人員一直找不到問題的原因在哪里。於是就花了點時間協助開發人員來找問題的根本原因。

     通過一些技術手段,定位到問題是由一個SQL語句引起的。

     SQL語句如下:

WITH PXQ_TASK_TEMP AS
 (SELECT A.DISTRIBUTE_DATE,
         A.APP_NO,
         A.TASK_ID,
         A.TASK_NO,
         A.ACTUAL_DISTRIBUTE_DATE,
         A.ACTUAL_RETURN_DATE,
         A.RELA_ID RELAID,
         A.VEHICLE_SERIAL,
         A.STATUS_CODE,
         A.MONTH,
         A.MADE_DPET_NO,
         A.DIST_TYPE_CODE,
         A.TASK_TYPE,
         A.RETURN_DATE,
         B.SOURCE_NODE_ID,
         B.RCV_NODE_NAME,
         B.RCV_NODE_ID,
         B.RCV_ID,
         C.DET_ID,
         C.EQUIP_CATEG,
         C.TASK_NUM,
         D.RELA_ID
    FROM D_DISTRIBUTE_TASK        A,
         D_RCV_TASK               B,
         D_DIST_TASK_DET          C,
         ECMS.D_VEHICLE_TASK_RELA D
   WHERE A.TASK_ID = B.TASK_ID(+)
     AND B.RCV_ID = C.RCV_ID(+)
     AND A.TASK_ID = D.TASK_ID(+)),
PXQ_TASK_CATEG AS
 (SELECT DISTINCT TASK_ID, RCV_ID, DET_ID, EQUIP_CATEG, TASK_NUM
    FROM PXQ_TASK_TEMP),
PXQ_TASK_SUM AS
 (SELECT V.NAME || ':' || SUM(TASK_NUM) TASK_SUM, MAX(PXQ.TASK_ID) TASK_ID
    FROM V_SP_CODE V, PXQ_TASK_CATEG PXQ
   WHERE CODE_TYPE LIKE 'equipCateg'
     AND VALUE = EQUIP_CATEG
   GROUP BY PXQ.TASK_ID, V.NAME)
SELECT DISTINCT AA.DISTRIBUTE_DATE PLAN_DATE,
                AA.APP_NO,
                AA.MONTH,
                AA.TASK_ID,
                AA.TASK_NO,
                AA.ACTUAL_DISTRIBUTE_DATE,
                AA.ACTUAL_RETURN_DATE,
                AA.RELAID,
                AA.VEHICLE_SERIAL EV_NO,
                AA.STATUS_CODE,
                AA.DIST_TYPE_CODE,
                AA.TASK_TYPE,
                AA.RETURN_DATE,
                (SELECT REPLACE(WMSYS.WM_CONCAT(NODE_NAME), ',', ';')
                   FROM ECMS.D_DISTRIBUTE_NODE
                  WHERE NODE_ID IN (SELECT DISTINCT SOURCE_NODE_ID
                                      FROM PXQ_TASK_TEMP
                                     WHERE TASK_ID = AA.TASK_ID)) SOURCE_NODE,
                (SELECT REPLACE(WMSYS.WM_CONCAT(NODE_NAME), ',', ';')
                   FROM ECMS.D_DISTRIBUTE_NODE
                  WHERE NODE_ID IN (SELECT DISTINCT RCV_NODE_ID
                                      FROM PXQ_TASK_TEMP
                                     WHERE TASK_ID = AA.TASK_ID)) RCV_NODE,
                (SELECT REPLACE(WMSYS.WM_CONCAT(TASK_SUM), ',', '/')
                   FROM PXQ_TASK_SUM
                  WHERE TASK_ID = AA.TASK_ID) PLAN_NUM,
                '' EV_NUM,
                '' SETTED_EV
  FROM PXQ_TASK_TEMP AA
 WHERE 1 = 1;

     把這個SQL語句放在開發庫可以正常執行,但是放在測試庫就報錯了。報錯信息為:ORA-00932:數據類型不一致:應為 -,但卻獲得CLOB。當時想到的就是兩個庫中可能有些表的數據庫數據結構不一致(如:字段的數據類型),經比較這個SQL語句中涉及到的表在兩個環境中的數據結構完全一致。這時想到的就是可能是某個函數導致了結果出現了LOB類型。經診斷是由oracle函數WMSYS.WM_CONCAT引起的。那么為什么會引起這樣的問題呢?兩套環境同樣是使用的oracle,程序也完全一致。首先想到的是可能oracle的WMSYS.WM_CONCAT函數存在版本差異。

     下面就進行了WMSYS.WM_CONCAT函數在oracle版本差異的驗證。在開發庫中執行SELECT * FROM v$version;顯示結果為:Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi;再在測試庫中執行SELECT * FROM v$version;顯示結果為:Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bi。說明oracle版本差異的猜測是對的。

     接下來看WMSYS.WM_CONCAT函數在不同oracle版本中到底存在什么差異。

     編寫測試SQL:

SELECT REPLACE(WMSYS.WM_CONCAT(NODE_NAME), ',', ';')
  FROM ECMS.D_DISTRIBUTE_NODE A
 WHERE NODE_ID IN (SELECT DISTINCT SOURCE_NODE_ID FROM D_RCV_TASK B);

     該SQL在開發庫中(即oracle版本為:Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi)執行結果為:

     

     該SQL在測試庫中(即oracle版本為:Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bi)執行結果為:

     

        oracle的WMSYS.WM_CONCAT函數在Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi版本中的結果是一個字符型的數據,而在Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi版本中是一個CLOB類型。而我們知道在SQL語句中若查詢了LOB字段是不能使用distinct,union,和group by等關鍵字的。這樣就完全解釋了那個SQL語句會在測試庫中報錯的原因了。

        最后將上面的SQL語句做了相關優化,且在不同oracle版本中通用。SQL語句修改后如下:

SELECT A.DISTRIBUTE_DATE PLAN_DATE,
       A.APP_NO,
       A.MONTH,
       A.TASK_ID,
       A.TASK_NO,
       A.ACTUAL_DISTRIBUTE_DATE,
       A.ACTUAL_RETURN_DATE,
       A.RELA_ID,
       A.VEHICLE_SERIAL EV_NO,
       A.STATUS_CODE,
       A.DIST_TYPE_CODE,
       A.TASK_TYPE,
       A.RETURN_DATE,
       (SELECT REPLACE(WMSYS.WM_CONCAT(NODE_NAME), ',', ';')
          FROM ECMS.D_DISTRIBUTE_NODE
         WHERE NODE_ID IN (SELECT DISTINCT SOURCE_NODE_ID
                             FROM D_RCV_TASK
                            WHERE TASK_ID = A.TASK_ID)) SOURCE_NODE,
       (SELECT REPLACE(WMSYS.WM_CONCAT(NODE_NAME), ',', ';')
          FROM ECMS.D_DISTRIBUTE_NODE
         WHERE NODE_ID IN (SELECT DISTINCT RCV_NODE_ID
                             FROM D_RCV_TASK
                            WHERE TASK_ID = A.TASK_ID)) RCV_NODE,
       (SELECT REPLACE(WMSYS.WM_CONCAT(V.NAME || ':' || SUM(C.TASK_NUM)),
                       ',',
                       '/')
          FROM V_SP_CODE V, D_DIST_TASK_DET C
         WHERE C.TASK_ID = A.TASK_ID
           AND V.CODE_TYPE LIKE 'equipCateg'
           AND V.VALUE = C.EQUIP_CATEG
         GROUP BY V.NAME) PLAN_NUM,
       '' EV_NUM,
       '' SETTED_EV
  FROM D_DISTRIBUTE_TASK A, ECMS.D_VEHICLE_TASK_RELA B
 WHERE A.TASK_ID = B.TASK_ID(+)
 GROUP BY A.DISTRIBUTE_DATE,
          A.APP_NO,
          A.MONTH,
          A.TASK_ID,
          A.TASK_NO,
          A.ACTUAL_DISTRIBUTE_DATE,
          A.ACTUAL_RETURN_DATE,
          A.RELA_ID,
          A.VEHICLE_SERIAL,
          A.STATUS_CODE,
          A.DIST_TYPE_CODE,
          A.TASK_TYPE,
          A.RETURN_DATE;

       通過這次問題的排查,我們知道在寫SQL語句的時候,若使用了WMSYS.WM_CONCAT函數,應盡量不要對查詢結果進行distinct,union,和group by操作,避免oracle版本的差異化。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM