Oracle 11g數(shù)據(jù)庫(kù)使用XML Table的BUG解決
Oracle 11g開(kāi)發(fā)項(xiàng)目時(shí),使用XML Table出現(xiàn)了BUG,現(xiàn)總結(jié)如下:?jiǎn)栴}其實(shí)很簡(jiǎn)單,就是我們?cè)陧?xiàng)目中使用了很多超級(jí)長(zhǎng)的SQL語(yǔ)句,之后導(dǎo)致SQL執(zhí)行效率低下,并且貌似導(dǎo)致了Oracle的SQL編譯空間溢出了。
出問(wèn)題的SQL:
- SELECT N1,N2
- FROM A1
- WHERE
- (N1='1' AND N2='a1') OR
- (N1='2' AND N2='a2') OR
- (N1='3' AND N2='a3') OR
- (N1='4' AND N2='a4') OR
- ....
BUG解析
當(dāng)然了真實(shí)的SQL文是不可能這么簡(jiǎn)單的,比這個(gè)要復(fù)雜的多。不過(guò)出問(wèn)題的部分基本就是這樣了,其實(shí)原來(lái)沒(méi)用AND/OR這種結(jié)構(gòu),用的是IN,但I(xiàn)N語(yǔ)句的參數(shù)不能超過(guò)2000個(gè)。所以就改成這個(gè)結(jié)構(gòu)了,這個(gè)結(jié)構(gòu)傳東西到是沒(méi)有限制了,但是會(huì)導(dǎo)致SQL文變長(zhǎng),而且由于數(shù)據(jù)的長(zhǎng)度不定。這些1和a1是前面產(chǎn)生的結(jié)果,所以不一定有多少組。所以都是直接拼在SQL里了。問(wèn)題很明顯,后果很嚴(yán)重。
BUG解決
因?yàn)橄到y(tǒng)已經(jīng)開(kāi)發(fā)很長(zhǎng)時(shí)間了,不能進(jìn)行太大的改動(dòng)。老系統(tǒng)就這樣,改的越多,錯(cuò)的越多,狂改代碼基本屬于自虐行為。所以我們引入了XMLTable來(lái)解決這個(gè)問(wèn)題,這還是一個(gè)DBA給的建議呢。
- SELECT N1,N2
- FROM A1
- WHERE (N1,N2) IN (
- SELECT X1,X2 FROM
- XMLTable('for $i in /T/REC return $i' PASSING XMLType(#str:CLOB#)
- COLUMNS X1 INTEGER PATH 'X1',
- X2 CHAR(2) PATH 'X2')
因?yàn)槭褂胕Batis的緣故,所以我使用了一個(gè)叫str的參數(shù),并且聲明為CLOB類型的,但str里放什么呢?
- <T>
- <REC><X1>1</X1><X2>a1</X2></REC>
- <REC><X1>2</X1><X2>a2</X2></REC>
- ....
- </T>
這個(gè)很明白了吧,就是把需要的數(shù)據(jù)通過(guò)XML的形式變成一個(gè)表,之后再和主表進(jìn)行子查詢進(jìn)行關(guān)聯(lián)。這樣做的好處就是把SQL文的長(zhǎng)度變換為參數(shù)的長(zhǎng)度了,雖然參數(shù)變長(zhǎng)了,但SQL文本身變短了。
總結(jié)
真正做的時(shí)候還遇到了一些問(wèn)題:首先,使用這個(gè)SQL的時(shí)候必須要在一個(gè)事務(wù)里,雖然他只是查詢,但一定要在事務(wù)里否則會(huì)出錯(cuò)。因?yàn)樵蹅兂绦蚶锸褂昧薈LOB數(shù)據(jù),所以要加載以下的Bean:
- <bean id="simpleExtractor"
- class="org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor">
- </bean>
- <bean id="oracleLobHandler"
- class="org.springframework.jdbc.support.lob.OracleLobHandler">
- <property name="nativeJdbcExtractor" ref="simpleExtractor"/>
- </bean>
SQLMap里需要加一個(gè)CLOB的TypeHandler,之后在變量里聲明一下#str:CLOB#就可是了。
- <typeHandler javaType="java.lang.String" jdbcType="CLOB"
- callback="org.springframework.orm.ibatis.support.ClobStringTypeHandler"/>
但還有一點(diǎn)需要注意,我查了很長(zhǎng)時(shí)間,因?yàn)?在iBatis里是關(guān)鍵字,這個(gè)關(guān)鍵字如果需要輸出的話就需要轉(zhuǎn)義,就要使用$代表一個(gè)$當(dāng)然#也是同理的。
關(guān)于Oracle 11g數(shù)據(jù)庫(kù)出現(xiàn)使用XML Table解決問(wèn)題的BUG的解決就介紹到這里了,希望本次的介紹能夠?qū)δ兴斋@!
【編輯推薦】


















