昨天在测试的时候发现,开发人员写的一段程序放在开发库中是好的,但是放在测试库中就会有问题。开发人员一直找不到问题的原因在哪里。于是就花了点时间协助开发人员来找问题的根本原因。

通过一些技术手段,定位到问题是由一个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版本的差异化。

转载请注明文章来源于:http://www.cnblogs.com/Automation_software/archive/2013/03/29/2988333.html

oracle中WMSYS.WM_CONCAT函数的版本差异的更多相关文章

  1. 【Oracle】wmsys.wm_concat函数字段值为空

    这个是因为字符集的问题,和空值是没关系的.其实已经取到了数据,可以验证一下返回的不是0,但是由于这个里面有个chr(0)字符,而且可能第一个字符就是chr(0),所以就显示得怪异的空现象.至于为何会出 ...

  2. Oracle 中wmsys.wm_concat拼接字符串,结果过长报错解决

    备忘:这个函数最大是4000,根据拼接列的长度,通过限制拼接条数来防止拼接字符串过长错误 --这个情况是从子表中读取出具,这里直接把它当做查询字段处理,在子表中有所有数据 select info.id ...

  3. oracle 12C wmsys.wm_concat()函数

    http://blog.itpub.net/31392094/viewspace-2149577/

  4. Oracle中的单行函数

    Oracle中的单行函数 1 字符函数 UPPER()--将字符串转换为大写 SELECT UPPER('abc') FROM dual; LOWER()-将字符串转换为小写 SELECT LOWER ...

  5. oracle 10g WMSYS.WM_CONCAT 函數的用法

    select t.rank, t.Name from t_menu_item t; 10 CLARK 10 KING 10 MILLER 20 ADAMS 20 FORD 20 JONES 20 SC ...

  6. Oracle中 Instr 这个函数

    http://www.jb51.net/article/42369.htm sql :charindex('字符串',字段)>0 charindex('administrator',MUserI ...

  7. 创建类似于Oracle中decode的函数

    -- 创建类似于Oracle中decode的函数create or replace function decode(variadic p_decode_list text[])returns text ...

  8. Oracle中的substr()函数 详解及应用

    注:本文来源于<Oracle中的substr()函数 详解及应用> 1)substr函数格式   (俗称:字符截取函数) 格式1: substr(string string, int a, ...

  9. MySQL之实现Oracle中的rank()函数的功能

      假设表格为student, 数据如下:   我们要在MySQL中实现Oracle中的rank()函数功能,即组内排序,具体来说: 就是对student表中按照课程(course)对学生(name) ...

随机推荐

  1. win10 默认锁屏路径

    C:\Users\YourUsername\AppData\Local\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\ ...

  2. java中检测-在运行时指定对象是否是特定类的一个实例---关键字 instanceof

    java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例.instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例. if(requ ...

  3. 61. mybatic insert异常:BindingException: Parameter 'name' not found【从零开始学Spring B】

    mybatic insert异常:BindingException: Parameter 'name' not found [从零开始学习Spirng Boot-常见异常汇总] 异常信息如下: nes ...

  4. POJ 3261 字符串上的k次覆盖问题

    题目大意: 给定一个数组,求一个最大的长度的子串至少出现过k次 一个子串出现多次,也就是说必然存在2个子串间的前缀长度为所求的值 通过二分答案,通过线性扫一遍,去判断出现次数,也就是说每次遇见一个he ...

  5. HDU1074 Doing Homework 状态压缩dp

    题目大意: 根据完成任务的截止时间,超时一天罚1分,求完成所有任务后的最小罚时 这里n最大为15,可以利用状态压缩来解决问题 /* 首先要明白的一点是状态1/0分别表示这件事做了还是没做 而1/0的位 ...

  6. noip模拟赛 旅行

    分析:一个贪心的想法是每次找到根的点权和最大的点进行操作,关键是怎么维护.每次找最大值,修改后会对这条链上每个点的子树上的点造成影响,可以用线段树来维护.找最大值就是区间求最大值嘛,对子树进行操作利用 ...

  7. 重启系统media服务

    1.adb shell 执行 stop media & start media 或者stop media ; start media 2.代码里执行 import android.os.Sys ...

  8. 2018/2/27 Activiti教程之创建流程篇(与Springboot整合版)一

    因为电脑还在托运中,现在手上这台垃圾电脑实在是没法玩微服务,所以趁着这两天玩玩Activiti吧. 说实话,在学习Activiti中走了N多弯路,最大的原因就是网上没有一个完整(好)的教程,甚至连官方 ...

  9. [NOIP2006] 提高组 洛谷P1066 2^k进制数

    题目描述 设r是个2^k 进制数,并满足以下条件: (1)r至少是个2位的2^k 进制数. (2)作为2^k 进制数,除最后一位外,r的每一位严格小于它右边相邻的那一位. (3)将r转换为2进制数q后 ...

  10. Linux下汇编语言学习笔记14 ---

    这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...