1. 程式人生 > >Oracle列轉行函式版本不相容解決方案

Oracle列轉行函式版本不相容解決方案

業務場景

本部落格記錄一下Oracle列轉行函式在Oracle11的一些不相容問題,vm_concat在一些業務場景是必須的。不過這個函式使用要謹慎,底層實現應該也是group by等等實現的,效能並不是特別好。這個函式在Oracle12是沒有的,在Oracle11是不太相容的,Oracle10可以正常使用。最近遇到這個問題,網上部落格很多都寫到了自定義列轉行函式的辦法去解決。但是這種辦法並不一定適用所有的業務場景。我並沒有採用。不過有些場景還是可以使用的。

網上優秀例子

下面是網路記錄比較詳細的例子
https://www.cnblogs.com/hanzongze/p/oracle-wm_concat.html

解決方案

通過自定義函式解決也是可以的,不過我並不是這樣做的。
下面介紹一下我的解決方法。首先分析一下,Oracle11不相容vm_concat列轉行函式,並不代表其它函式不相容,或許可以找到其它代替的,通過找資料,發現了Oracle11提供的另外一個函式:listagg()函式
語法:listagg(引數,'分隔符') within group(order by 引數id)
列子:to_char(listagg(ur.user_role,',' ) within GROUP (order by (ur.user_role))) userrole,

原來SQL:

select u.user_sex,
       u.full_name,
       u.user_code,
       to_char(wm_concat(ur.user_role)) userrole,
       to_char(wm_concat(r.role_name)) rolename,
       to_char(r.role_type) roletype,
       u.status
  from t_user u
  left outer join t_user_role ur
    on ur.user_code = u.user_code
  left outer join t_role r
    on r.user_role = ur.user_role

首先通過SQL獲取一下oracle版本號

<!-- 獲取oracle版本資訊 -->
<select id="getOracleVersion" resultType="string">
    SELECT * FROM v$version WHERE banner LIKE 'Oracle%'
</select>

下面程式碼僅供參考,就是獲取oracle版本號,然後傳到mybatis的xml檔案

String oracleVersion = approveConfigDao.getOracleVersion();
//eg:Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
String[] bannerArr = oracleVersion.split(" ");
oracleVersion = bannerArr[2];
LOG.info("oracle版本:"+oracleVersion);
map.put("oracleVersion", oracleVersion);

orm框架是用mybatis的,所以sql稍微改一下,oracle10調vm_concat,oralce11的調listagg函式

select u.user_sex,
       u.full_name,
       u.user_code,
<choose>
    <when test="oracleVersion=='11g' or oracleVersion=='12g'">
            to_char(listagg(ur.user_role,',' ) within GROUP (order by (ur.user_role))) userrole,
            to_char(listagg(r.role_name,',' ) within GROUP (order by (r.role_name))) rolename,
        </when>
        <otherwise>
            to_char(wm_concat(ur.user_role)) userrole ,
            to_char(wm_concat(r.role_name)) rolename ,
        </otherwise>
</choose>
to_char(r.role_type) roletype,
       u.status
  from t_user u
  left outer join t_user_role ur
    on ur.user_code = u.user_code
  left outer join t_role r
    on r.user_role = ur.user_role