WEB开发网      濠电姷鏁告慨鐑藉极閸涘﹥鍙忛柣鎴f閺嬩線鏌涘☉姗堝姛缂佺娀绠栭弻宥堫檨闁告挻姘ㄩ幑銏犫槈濞嗘劕顎撻梺鍛婂姇瀵爼骞栭幇顔炬/闁告挆鍕畬闂佸疇顫夐崹鍧楀箖閳哄啠鍋撻崷顓炐㈡い銉︾箞濮婂搫效閸パ€鍋撳Δ鍛;闁规崘顕ф闂佸憡娲﹂崹鎵不濞戙垺鐓曟い鎰剁稻缁€鍐┿亜鎼达紕效婵﹨娅g划娆忊枎閹冨闂備礁鎽滄慨鐢稿礉濞嗘劒绻嗛柣銏⑶圭粈瀣亜閺嶃劏澹橀柛鐐姂濮婃椽妫冨ù銈嗙⊕閹峰懘骞撻幒宥咁棜闂備礁婀遍崕銈夈€冮崱娑樼厱闁圭儤顨嗛悡鏇㈡煛閸ャ儱濡煎ù婊勭矋閵囧嫯绠涢敐鍛睄闂佸搫澶囬埀顒€纾弳鍡涙倵閿濆骸澧伴柡鍡欏█閺屟勫濞嗘垵鍩岄梺闈涙鐢帡锝炲┑瀣亗閹艰揪绲奸悽鑽ょ磽娴h娈曢柛銊ョ仢椤繒绱掑Ο璇差€撶紓浣圭☉椤戝懎鈻撻鐐╂斀妞ゆ梹鏋婚崗顒傜磼閻樿櫕宕岄柕鍡曠椤繈骞囨担鍏夋瀸濠电姷鏁告慨顓㈠磻閹捐秮褰掓晲閸モ斂鈧﹪鏌¢埀顒佺鐎n偆鍘藉┑鈽嗗灡椤戞瑩宕电€n兘鍋撶憴鍕仩闁稿氦绮鹃悘鍐⒑缂佹◤顏勵嚕閸洖鐤柣鎰暩绾惧ジ鏌涚仦鐐殤閺佸牓鎮楃憴鍕缂侇喖绻樿棟閻庨潧鎽滃Λ顖炴煙椤栧棔绀佹禒顕€鎮楀▓鍨灈闁绘牜鍘ч悾鐑芥偂鎼存ɑ顫嶅┑鈽嗗灟鐠€锕傛倵瀹曞洨纾介柛灞剧懅閸斿秵銇勯妸銉︻棞闁伙絾绻堥獮鏍ㄦ媴濮濆本鎲伴梻浣虹帛濡啴藟閹捐姹查悗锝庡枟閻撶喐淇婇妶鍌氫壕闂佺粯顨呭Λ妤呭煝閹炬緞鏃堝川椤旇瀚奸梺鑽ゅТ濞茬娀鍩€椤掑啯鐝柣蹇婂亾闂傚倷绀侀幖顐﹀箠閹邦厽鍙忛柟缁㈠枟閸嬧晠鏌i妶搴$仜濞存粌缍婇弻鐔兼倻濡偐鐣洪梺鍝勬噺缁诲牆顫忓ú顏咁棃婵炴垶鑹鹃。鍝勨攽閳藉棗浜濋柣鐔叉櫊閵嗕礁鈻庨幒鏃傛澑闂佸搫鍟崐濠氭儊閸儲鈷戞慨鐟版搐閻忓弶绻涙担鍐插椤╃兘鏌ㄩ弴鐐测偓褰掓偂閺囥垺鐓忓┑鐐茬仢閸斻倝鏌涢埡瀣ɑ妞ゃ劊鍎甸幃娆撳级閹存繍娼氭俊銈囧Х閸嬬偤鏁冮姀銈冣偓浣糕枎閹炬潙娈愰梺鍐叉惈椤戝洭鐛姀銈嗏拻闁稿本鐟︾粊鐗堛亜椤愩埄妲搁柣锝呭槻铻i柤娴嬫櫇閻撳顪冮妶鍡橆梿闁跨喆鍎茬粋宥堛亹閹烘挾鍘甸梺缁樺灦钃遍悘蹇e幖闇夋繝濠傚暟缁夌儤鎱ㄦ繝鍛仩缂佽鲸甯掕灒闁惧繘鈧稒顢橀梻鍌欑劍鐎笛兠哄澶婄柧婵炴垶绮庢禍閬嶆⒒娴e憡鍟炴繛璇х畵瀹曞綊鏌嗗鍛幈闂佺鎻梽鍕偂濞嗘挻鐓犳繛鏉戭儐濞呭懎霉閻樺磭鐭婇柍瑙勫灴閸ㄩ箖鎮欓挊澶夊垝闂備浇顕栭崰妤呫€冮崨鏉戠叀濠㈣埖鍔曠粻鎶芥煙閹屽殶鐟滄澘娲ㄧ槐鎾诲磼濞嗘垼绐楅梺鍝ュУ閻楃娀銆侀弽顓炲窛闁圭⒈鍘介弲锝夋⒑缁嬭法绠抽柛妯犲懏顐介柣鎰節缁诲棙銇勯弽銊х煂閻㈩垱绋掔换娑㈠川椤撶喎鏋犲┑顔硷功缁垶骞忛崨瀛樺仭闂侇叏绠戝▓婵堢磽閸屾瑦绁版い鏇嗗洤纾归柛顭戝櫘閸ゆ洜绱撴担璐細缂佲檧鍋撻梻浣规偠閸庮垶宕濆鍛瀺闁搞儺鍓氶埛鎴犵磼鐎n偄顕滄繝鈧幍顔剧<閻庯綆鍋呭畷宀€鈧娲忛崹浠嬪箖娴犲宸濆┑鐘插楠炴姊洪悷鏉挎倯闁伙綆浜畷瑙勭節濮橆剛鍘愰梺鍝勬储閸ㄦ椽鎮¢妷锔藉弿婵☆垰鐏濋悡鎰版煟閹捐泛鏋涢柣鎿冨亰瀹曞爼濡烽妷銉バ戠紓鍌欑椤戝牆鐣烽悽鍨潟闁圭儤姊荤壕鍏间繆椤栨繂浜归柣锝堟缁辨挻鎷呴搹鐟扮缂備浇顕ч悧鍡涙偩瀹勯偊娼ㄩ柍褜鍓氭穱濠傤潰瀹€濠冃ㄧ紓鍌欐祰妞村摜鎹㈤崼婵愭綎缂備焦蓱婵绱掑☉姗嗗剰婵炲牊鍔欏娲箹閻愭彃顬嗛梺鍛婎殔閸熷潡鎮鹃悜绛嬫晬闁绘劘灏欐鍥⒑閻熼偊鍤熷┑顕€娼ч埢鎾淬偅閸愨斁鎷虹紓鍌欑劍钃遍柍閿嬪浮閺屽秴鐣¢幍顔尖叺閻庢鍣崑濠傜暦閹烘鍊烽悗鐢登归獮鍫ユ⒒娴g懓鈻曢柡渚囧櫍瀹曟垿骞樼紒妯煎幐闂佸憡渚楅崰姘跺箠閸涱喕绻嗛柛娆忣槸婵洭鎽堕敐澶嬪仩婵炴垶甯掓晶鏌ユ煛閸屾浜鹃梻鍌氬€烽懗鍓佸垝椤栫偛绀夐柡鍥╁€i悢鍝ョ瘈闁搞儜鍐╁劒闂備胶绮弻銊╂儍濠靛缁╅柤鎭掑劘娴滄粓鏌¢崘銊﹀妞ゃ儱顦甸弻娑㈠棘鐠囨祴鍋撳┑瀣闁割偅娲橀崐鐑芥煟閹寸偍缂氶柛姗€浜跺娲传閸曨剙鍋嶉梺鍛婃煥閺堫剟寮查崼鏇ㄦ晬闁绘劕顕崢鍗炩攽閻愬弶顥滅紒缁樺笧缁粯绻濆顓犲幐闁诲繒鍋熼弲顐f櫏闁诲氦顫夊ú锕傚磻婵犲倻鏆﹂柣鏃傗拡閺佸棝鏌嶈閸撴瑩鍩㈠澶嬫櫜闁搞儮鏅濋敍婵囩箾鏉堝墽绋荤憸鏉垮暞缁傚秹鎮欓鍌滅槇闂侀潧楠忕徊鍓ф兜閻愵兙浜滈柟瀛樼箖瀹告繄绱掗鍓у笡闁靛牞缍佸畷姗€鍩¢崘銊ョ闂備浇顕х€涒晝绮欓幒鎴犲箵閻犳亽鍔庢稉宥嗘叏濡炶浜鹃梺鍝勮閸斿矂鍩ユ径濞㈢喐寰勯惂鍝ョɑ闁靛洤瀚版俊鎼佹晲閸涱厼袝闂備浇顕栭崰妤呮偡閳哄懌鈧線寮崼婵堫槹濡炪倖鎸荤换鍕矆閸曨垱鈷掗柛灞剧懄缁佺増銇勯弴鐔哄⒌鐎规洑鍗冲浠嬵敃閵堝浂妲稿┑鐘垫暩婵挳宕愭繝姘辈闁挎洖鍊归悡娆愩亜閺嶎偄浠滃ù婊呭娣囧﹪鎳犳0婵嗘闂佸疇顫夐崹鍧楀春閸曨垰绀冮柕濞у懌鍋″┑锛勫亼閸娿倝宕㈡ィ鍐ㄧ婵☆垯璀﹂崵鏇㈡偣閸ャ劎銈存俊鎻掔墦閺屾洝绠涢弴鐑嗘綌闂佸啿鎼幊蹇涙偂韫囨搩鐔嗛悹楦挎婢ф洟鏌涢弮鈧幐鎶藉蓟濞戙垹妫樻繛鍡欏亾妤旂紓鍌欐祰妞存悂骞愭繝姘闁告侗鍨抽惌娆撳箹鐎涙ɑ灏ù婊堢畺閺屾稑鈹戦崟顐㈠Б闂佹椿鍘介幐楣冨箟閹间焦鍋嬮柛顐g箘閻熴劑姊洪崫鍕靛剮缂佽埖宀稿濠氭偄閻撳海顦悷婊冪箳閺侇喖鈽夐姀锛勫幐闂佸憡渚楅崰妤呭磹閹扮増鐓涢悘鐐额嚙婵倿鏌熼鍝勨偓婵嗙暦閹烘垟妲堟慨妤€妫旂槐锟� ---闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌i幋锝呅撻柛濠傛健閺屻劑寮崼鐔告闂佺ǹ顑嗛幐鍓у垝椤撶偐妲堟俊顖氭惈缁犺鈹戦悙鍙夆枙濞存粍绮撻幃鈥斥槈閵忥紕鍘卞┑鐐村灥瀹曨剟鐛Ο姹囦簻闁哄倹瀵чˉ銏℃叏婵犲懏顏犻柟鐟板婵℃悂濡烽敂鎯х稈闂傚倷鑳堕幊鎾诲吹閺嶎厼绠柨鐕傛嫹
开发学院数据库DB2 使用XQuery查询DB2 XML数据 阅读

使用XQuery查询DB2 XML数据

 2006-08-21 22:09:58 来源:WEB开发网 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾剧懓顪冪€n亜顒㈡い鎰Г閹便劌顫滈崱妤€骞婄紓鍌氬€瑰銊╁箟缁嬫鍚嬮柛顐線缂冩洟姊婚崒娆戭槮婵犫偓闁秵鎯為幖娣妼缁愭鏌″搴′簽濞戞挸绉甸妵鍕冀椤愵澀娌梺缁樻尪閸庣敻寮婚敐澶婂嵆闁绘劖绁撮崑鎾诲捶椤撴稑浜炬慨妯煎亾鐎氾拷闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾剧懓顪冪€n亝鎹i柣顓炴閵嗘帒顫濋敐鍛婵°倗濮烽崑娑⑺囬悽绋挎瀬闁瑰墽绮崑鎰版煙缂佹ê绗ч柍褜鍓﹂崣鍐潖閸濆嫅褔宕惰娴犲ジ姊虹拠鑼闁煎綊绠栭幃楣冩倻閽樺鎽曢梺闈涱檧婵″洭宕㈤悽鍛娾拺閻熸瑥瀚烽崯蹇涙煕閻樺磭澧甸柕鍡楀€圭缓浠嬪川婵犲嫬骞堥梺纭呭閹活亞妲愰弴鐔哄ⅰ闂傚倷绶氬ḿ褍煤閵堝洠鍋撳顐㈠祮闁绘侗鍣i獮鎺懳旈埀顒傜不閿濆棛绡€闂傚牊绋戦弳娆徝瑰⿰鍫㈢暫闁哄矉缍佹慨鈧柍鎯版硾濠€杈ㄧ珶閺囩喓绡€婵﹩鍘鹃崢鐢告⒑缂佹ê濮﹂柛鎾村哺閹ɑ娼忛妸銈囩畾闂佸湱绮敮鐐存櫠濞戞氨纾肩紓浣贯缚濞插鈧娲栧畷顒冪亙闂佸憡鍔曢崯鐘诲礈濠靛牊宕叉繛鎴炨缚閺嗗棗鈹戦悩杈厡闁轰焦鐗滅槐鎾存媴娴犲鎽甸梺鍦嚀濞层倝鎮鹃悜钘夌闁规惌鍘介崓鐢告⒑閻熸澘鎮侀柣鎺炵畵閹骞栨担鍏夋嫽婵炶揪绲块崕銈夊吹閳ь剟姊洪幖鐐测偓鏍偋閻樿崵宓侀煫鍥ㄧ⊕閺呮悂鏌ㄩ悤鍌涘濠电姷鏁告慨鐑藉极閸涘﹥鍙忛柣鎴f閺嬩線鏌涘☉姗堟敾闁告瑥绻戦妵鍕箻閸楃偟浠肩紓浣哄閸ㄥ爼寮诲☉銏犵疀闂傚牊绋掗悘鍫ユ倵閻熺増鍟炵紒璇插暣婵$敻宕熼姘鳖啋闁诲酣娼ч幗婊堟偩婵傚憡鈷戠痪顓炴媼濞兼劖绻涢懠顒€鏋庢い顐㈢箳缁辨帒螣閼测晜鍤岄梻渚€鈧偛鑻晶顔肩暆閿濆牆鍔垫い锔界叀閹繝濡舵径瀣帾闂佸壊鍋呯换鍐磻椤忓懐绠剧€瑰壊鍠曠花濠氬箚閻斿吋鈷戦悗鍦У閵嗗啴鏌ら崘鑼煟鐎规洘绻堥弫鍐焵椤掑嫧鈧棃宕橀鍢壯囨煕閳╁喚娈橀柣鐔稿姍濮婃椽鎮℃惔鈩冩瘣闂佺粯鐗曢妶绋跨暦閻戞ḿ绡€闁搞儜鍐ㄧギ闂備線娼ф蹇曟閺囥垹鍌ㄦい蹇撶墛閳锋垿鏌熼懖鈺佷粶闁告梹顨婇弻锟犲川椤旈敮濮囩紓浣稿€圭敮鐔妓囩€靛摜纾奸弶鍫涘妼缁楁碍绻涢悡搴g闁糕斁鍓濋幏鍛存煥鐎e灚缍楅梻鍌氬€峰ù鍥ь浖閵娾晜鍊块柨鏇炲€哥粻鏌ユ煕閵夘喖澧柡瀣╃窔閺岀喖宕滆鐢盯鏌¢崨顔藉€愰柡灞诲姂閹倝宕掑☉姗嗕紦闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾剧懓顪冪€n亜顒㈡い鎰Г閹便劌顫滈崱妤€骞婄紓鍌氬€瑰銊╁箟缁嬫鍚嬮柛顐線缂冩洟姊婚崒娆戭槮婵犫偓闁秵鎯為幖娣妼缁愭鏌″搴′簽濞戞挸绉甸妵鍕冀椤愵澀娌梺缁樻尪閸庣敻寮婚敐澶婂嵆闁绘劖绁撮崑鎾诲捶椤撴稑浜炬慨妯煎亾鐎氾拷  闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌i幋锝呅撻柛銈呭閺屻倝宕妷锔芥瘎婵炲濮靛銊ф閹捐纾兼繛鍡樺笒閸橈紕绱撴笟鍥ф珮闁搞劌鐖兼俊鎾礃椤旂厧绐涢梺鍝勵槹閸ㄥ綊宕㈠ú顏呭€垫鐐茬仢閸旀碍銇勯敂璇茬仸鐎规洩绻濋獮搴ㄦ嚍閵壯冨妇闂傚⿴鍋勫ú锕€煤閺嶃劎澧¢梻鍌欐祰椤曆呪偓鍨浮瀹曟粓鎮㈡總澶嬬稁闂佹儳绻愬﹢杈╁閸忛棿绻嗘い鏍ㄧ閹牊銇勯銏㈢劯婵﹨娅i幏鐘绘嚑椤掑偆鍞规繝娈垮枟鑿ч柛鏃€鍨垮畷娲焵椤掍降浜滈柟鍝勭Ф椤︼箓鏌涢妶搴″⒋闁哄本鐩獮妯兼崉閻戞ḿ鈧顪冮妶搴′簻缂佺粯鍔楅崣鍛渻閵堝懐绠伴悗姘煎墴閹顢橀悜鍡樺瘜闂侀潧鐗嗗Λ娆戠矆閳ь剟姊洪悷鏉挎毐闂佸府绲介悾宄扳堪閸曨偒鍤ら柣搴㈢⊕鑿ら柟閿嬫そ濮婄粯绗熼崶褌绨介梺绋款儐閻╊垶骞婇悢纰辨晬婵炴垶鐟﹂悵宄邦渻閵堝棙鐓ュ褏鏅竟鏇㈡偂鎼搭喚鍞甸柣鐘烘鐏忋劑宕濋悢铏圭<濠㈣泛瀛╅鐘绘煃瑜滈崜姘额敊閺嶎厼绐楅柡宥庡幐閳ь剨绠撻弻銊р偓锝傛櫇缁犳艾鈹戦鐣岀畵闁活厼鐗嗗嵄闁绘垼濮ら埛鎴犵磼鐎n偒鍎ラ柛搴㈠姍閺岀喖鎮烽悧鍫熸倷闁捐崵鍋ら弻娑㈠箛閳轰礁唯濠碘剝褰冮悧濠勬崲濞戙垹骞㈡俊銈呭暟椤斿鈹戦悙鑼闁挎洏鍨归~蹇曠磼濡顎撴俊鐐差儏缁ㄨ偐鎲伴崱娆戠=闁稿本姘ㄨⅵ闂佺ǹ顑嗛幐鑽ゆ崲濞戞埃鍋撳☉娆嬬細闁活厹鍊濋弻娑㈠箻鐠虹儤鐏堥悗瑙勬礃濡炰粙宕洪埀顒併亜閹哄秹妾峰ù婊勭矒閺岀喖鎮滃Ο铏逛淮闂侀€炲苯澧紓宥咃工椤曪綁骞庣粵瀣櫌闂佸憡娲﹂崜娑㈠储闁秵鐓熼幖鎼灣缁夐潧霉濠婂懎鍘撮柣鎿冨墴椤㈡宕掑Δ鈧禍楣冩偡濞嗗繐顏痪鎯ь煼閺屾稑螖閳ь剟宕崸妤婃晪闁挎繂顦壕褰掓煟閺囨氨鍔嶉棄瀣⒒閸屾瑧顦﹂柟纰卞亜铻為悗闈涙憸娑撳秹鏌熼幑鎰靛殭闁藉啰鍠栭弻鏇熺箾閻愵剚鐝曢梺绋款儏濡繈寮诲☉姘勃闁告挆鈧Σ鍫濐渻閵堝懘鐛滈柟鍑ゆ嫹
核心提示:关于 XQuery XQuery 在很多关键方面都与 SQL 有所不同,这很大程度上是因为这两种语言是针对两种具有不同特征的数据模型而设计的,使用XQuery查询DB2 XML数据,xml(标准化越来越近了) 文档包含层次结构,并且有其固有的顺序,我们将深入研究另一个有趣的话题:如何开发利用 DB2 xml(标准化

关于 XQuery
XQuery 在很多关键方面都与 SQL 有所不同,这很大程度上是因为这两种语言是针对两种具有不同特征的数据模型而设计的。xml(标准化越来越近了) 文档包含层次结构,并且有其固有的顺序。而基于 SQL 的数据库管理系统所支持的表格数据结构是平面的(flat),并且是基于集合的;因此,行之间不存在顺序。

这两种数据模型的不同导致它们各自的查询语言有很多基本的不同。例如,XQuery 支持路径表达式,以允许程序员在 xml(标准化越来越近了) 的层次结构中导航,而纯 SQL(没有 xml(标准化越来越近了) 扩展)则不支持。XQuery 支持有类型的和无类型的数据,而 SQL 数据总是以指定类型定义的。XQuery 没有 null 值,因为 xml(标准化越来越近了) 文档会忽略缺失的或未知的数据。当然,SQL 使用 null 来表示缺失的或未知的数据值。XQuery 返回一系列的 xml(标准化越来越近了) 数据,而 SQL 则返回各种 SQL 数据类型的结果集。

这只是 XQuery 和 SQL 之间的基本不同点中的一部分。提供一份详尽的列表超出了本文的范围,不过即将发表的 IBM Systems Journal 将更详细地讨论这些语言的不同。现在我们就探索一下 XQuery 语言的一些基本方面,并看看如何使用它来查询 DB2 Viper 中的 xml(标准化越来越近了) 数据。

样本数据库

本文中的查询访问在 “DB2 Viper 快速入门”(developerWorks,2006 年 4 月)中创建的样本表。清单 1 给出了样本数据库中 “items” 和 “clients” 表的定义:

清单 1. 表定义



create table items (

id int Prima(最完善的虚拟主机管理系统)ry key not null,

brandname varchar(30),

itemname varchar(30),

sku int,

srp decimal(7,2),

comments xml(标准化越来越近了)

)

create table clients(

id int Prima(最完善的虚拟主机管理系统)ry key not null,

name varchar(50),

status varchar(10),

contactinfo xml(标准化越来越近了)

)

图 1 中显示了 “items.comments” 列中包含的样本 xml(标准化越来越近了) 数据,而 图 2 中则显示了 “clients.contactinfo” 列中包含的样本 xml(标准化越来越近了) 数据。随后的例子查询将引用这两个 xml(标准化越来越近了) 文档中的一个或两个中的特定元素。

图 1. 存储在 “items” 表的 “comments” 列中的样本 xml(标准化越来越近了) 文档

使用XQuery查询DB2 xml(标准化越来越近了)数据(图一)

图 2. 存储在 “clients” 表的 “contactinfo” 列中的样本 xml(标准化越来越近了) 文档

使用XQuery查询DB2 xml(标准化越来越近了)数据(图二)

查询环境

本文中的所有查询都是通过交互方式发出的。这可以通过 DB2 命令行处理器或 DB2 Control Center 的 DB2 Command Editor 来完成。本文中的屏幕图像和说明主要使用后一种方式。(DB2 Viper 还附带了一个基于 Eclipse 的 Developer Workbench,它可以帮助程序员以图形化的方式构造查询。本文不讨论应用程序开发问题和 Developer Workbench。)

要使用 DB2 Command Editor,启动 Control Center,并选择 Tools -> Command Editor。这时将出现如 图 3 所示的窗口。在上面的面板中输入查询,单击左上角的绿色箭头运行该查询,然后可以在下面的面板中或者在 “Query Results” 选项卡中查看输出。

图 3. DB2 Command Editor,可以从 DB2 Control Center 中启动

使用XQuery查询DB2 xml(标准化越来越近了)数据(图三)

XQuery 例子

与在 “用 SQL 查询 DB2 xml(标准化越来越近了) 数据” 中一样,本文将逐步讲解一些常见的业务场景,并展示如何使用 XQuery 来满足对 xml(标准化越来越近了) 数据的请求。本文还探索了需要将 SQL 嵌入在 XQuery 中的更复杂的情景。

XQuery 提供了一些不同类型的表达式,这些表达式可以随意组合。每个表达式返回一系列的值,这些值又可以作为其他表达式的输入。最外面的表达式的结果就是查询的结果。

本文主要讨论两种重要的 XQuery 表达式:“FLWOR” 表达式和路径表达式。FLWOR 表达式非常像 SQL 中的 SELECT-FROM-WHERE 表达式 —— 它用于对由多项组成的一个列表进行迭代,并且可以选择返回通过在每一项上进行计算得到的值。而路径表达式则可以在分层的 xml(标准化越来越近了) 元素之间进行导航,并返回在路径末端找到的元素。

与 SQL 中的 SELECT-FROM-WHERE 表达式类似,XQuery FLWOR 表达式可以包含数个以某个关键词开头的子句。在 FLWOR 表达式中,有以下用于作为子句开头的关键字:
  • for:对输入序列进行迭代,依次将一个变量绑定到每个输入项
  • let:声明一个变量并为之赋值,可能是一个包含多项的列表
  • where:指定过滤查询结果的标准
  • order by:指定结果的排序顺序
  • return:定义所返回的结果
XQuery 中的路径表达式由一系列的 “步(step)” 组成,之间以斜杠隔开。在最简单的形式中,每一步在 xml(标准化越来越近了) 层次中向下导航,以发现由前一步返回的元素的孩子。路径表达式中的每一步还可以包含一个谓词,用于过滤该步返回的元素,只保留满足某种条件的元素。例如,假设变量 $clients 被绑定到包含 <Client> 元素的 xml(标准化越来越近了) 文档的一个列表,则 4 步路径表达式 $clients/Client/Address[state = "CA"]/zip 将返回居住在加利福尼亚的客户的邮政编码。

在很多情况下,可以任意使用 FLWOR 表达式或路径表达式编写查询。

使用 DB2 XQuery 作为顶层查询语言

要在 DB2 Viper 中直接执行 XQuery(而不是将它嵌入在 SQL 语句中),必须以关键字 xquery 作为查询的开头。这个关键字将指示 DB2 调用它的 XQuery 解析器来处理请求。注意,只有在使用 XQuery 作为最外层(顶层)语言的时候才需要这么做。如果是将 XQuery 表达式嵌入在 SQL 中,则不需要在语句之前加上 xquery 关键字。但是,本文使用 XQuery 作为基本语言,因此所有查询之前都加上 xquery。

当 XQuery 被作为顶层语言时,它需要一个输入数据的源。XQuery 获得输入数据的一种方式是调用一个名为 db2-fn:xml(标准化越来越近了)column 的函数,调用时带一个参数,表明 DB2 表中 xml(标准化越来越近了) 列所在的表名和该列的列名。db2-fn:xml(标准化越来越近了)column 函数返回存储在给定列中的一系列的 xml(标准化越来越近了) 文档。例如,下面的查询返回一系列包含客户联系方式信息的 xml(标准化越来越近了) 文档:

清单 2. 返回客户联系方式数据的简单 XQuery



xquery db2-fn:xml(标准化越来越近了)column('CLIENTS.CONTACTINFO')



您可能还记得,在我们的数据库模式中(参见 “样本数据库” 小节),我们将那些 xml(标准化越来越近了) 文档存储在 “clients” 表的 “contactinfo” 列中。注意,这里的列名和表名是大写的。这是因为表名和列名在被写入到 DB2 的内部编目之前通常要换成大写形式。由于 XQuery 是大小写敏感的,因此小写的表名和列名不能与 DB2 编目中的大写名称相匹配。

检索特定的 xml(标准化越来越近了) 元素

首先我们来看一个基本的任务。假设您要检索所有提供了有关传真信息的客户的传真号。清单 3 给出了编写该查询的一种方式:

清单 3. 检索客户传真数据的 FLWOR 表达式



xquery

for $y in db2-fn:xml(标准化越来越近了)column('CLIENTS.CONTACTINFO')/Client/fax

return $y



第一行指示 DB2 调用它的 XQuery 解析器。接下来的一行指示 DB2 对包含在 CLIENTS.CONTACTINFO 列中的 Client 元素的 fax 子元素进行迭代。每个 fax 元素被依次与变量 $y 绑定。第三行指出在每次迭代中返回 $y 的值。结果为一系列的 xml(标准化越来越近了) 元素,如 清单 4 所示:

清单 4. 上述查询的示例输出



<fax>4081112222</fax>

<fax>5559998888</fax>



随便提一下,这里的输出还将包含与本文关系不大的一些信息:xml(标准化越来越近了) 版本和编码数据,例如 <?xml(标准化越来越近了) version="1.0" encoding="windows-1252" ?>,以及 xml(标准化越来越近了) 名称空间信息,例如 <fax xml(标准化越来越近了)ns:xsi="http://www.w3.org/2001/xml(标准化越来越近了)Schema-instance">。为了使输出更简单,本文省略了这些信息。然而,对于很多 xml(标准化越来越近了) 应用程序来说这些信息可能很重要。如果使用 DB2 命令行处理器来运行查询,那么可以使用 -d 选项来省略 xml(标准化越来越近了) 声明信息,还可以使用 -i 选项以一种美观的方式打印结果。

清单 3 中显示的查询也可以用一种更简单的三步路径表达式来表达,如 清单 5 所示:

清单 5. 检索客户传真数据的路径表达式



xquery

db2-fn:xml(标准化越来越近了)column('CLIENTS.CONTACTINFO')/Client/fax

路径表达式的第一步调用 db2-fn:xml(标准化越来越近了)column 函数从 CLIENTS 表的 CONTACTINFO 列获得一个 xml(标准化越来越近了) 文档的列表。第二步返回这些文档中的所有 Client 元素,第三步则返回嵌入在这些 Client 元素中的 fax 元素。

如果您无兴趣通过查询获得 xml(标准化越来越近了) 片段,而只想要符合条件的 xml(标准化越来越近了) 元素值的文本表示,那么可以在 return 子句中调用 text() 函数,如 清单 6 所示:

清单 6. 两个用于检索客户传真数据的文本表示的查询



xquery

for $y in db2-fn:xml(标准化越来越近了)column('CLIENTS.CONTACTINFO')/Client/fax

return $y/text()

(or)

xquery

db2-fn:xml(标准化越来越近了)column('CLIENTS.CONTACTINFO')/Client/fax/text()

上述查询的输出如 清单 7 所示:

清单 7. 上述查询的示例输出



4081112222

5559998888



这些示例查询的结果都相当简单,因为 fax 元素是基于基本数据类型的。当然,元素也可能基于复杂的数据类型 —— 即包含子元素(或嵌套层次结构)。例如客户联系方式信息中的 Address 元素就是这样。根据 “DB2 Viper 快速入门”(developerWorks,2006 年 4 月)中定义的模式,该元素包含街道地址、门牌号、所在城市、州、国家以及邮政编码。考虑清单 8 中的 XQuery 将返回什么结果:

清单 8. 检索复杂 xml(标准化越来越近了) 类型的 FLWOR 表达式



xquery

for $y in db2-fn:xml(标准化越来越近了)column('CLIENTS.CONTACTINFO')/Client/Address

return $y

如果您猜到返回的结果是包含 Address 元素及其所有子元素的一系列的 xml(标准化越来越近了) 片段,那就对了。清单 9 给出了一个例子:

清单 9. 上述查询的示例输出



<Address>

<street>5401 Julio Ave.</street>

<city>San Jose</city>

<state>CA</state>

<zip>95116</zip>

</Address>

. . .

<Address>

<street>1204 Meridian Ave.</street>

<apt>4A</apt>

<city>San Jose</city>

<state>CA</state>

<zip>95124</zip>

</Address>

注意: 为了易于阅读,这里的示例输出作了格式上的调整。DB2 Command Editor 是在一行中显示每个客户地址记录的。

过滤 xml(标准化越来越近了) 元素值

您可以修改上述 XQuery 例子,缩小选择范围。例如,我们来看看如何返回居住在邮政编码为 95116 的地区的所有客户的邮递地址。

与您想像的一样,通过 XQuery where 子句可以根据 xml(标准化越来越近了) 文档中 zip 元素的值来过滤结果。清单 10 说明了如何在 清单 8 中的 FLWOR 表达式中添加一个 where 子句,以获得您感兴趣的地址信息:

清单 10. 带有 “where” 子句的 FLWOR 表达式



xquery

for $y in db2-fn:xml(标准化越来越近了)column('CLIENTS.CONTACTINFO')/Client/Address

where $y/zip="95116"

return $y

这里添加的 where 子句很容易理解。for 子句依次将变量 $y 绑定到每个地址。where 子句包含一个小型的路径表达式,该表达式从每个地址向下定位到其内嵌的 zip 元素。只有当这个 zip 元素等于 95116 时,where 子句才为 true(相应的地址被保留)。

通过在路径表达式中添加一个谓词也可以得到相同的结果,如 清单 11 所示:

清单 11. 带附加过滤谓词的路径表达式



xquery

db2-fn:xml(标准化越来越近了)column('CLIENTS.CONTACTINFO')/Client/Address[zip="95116"]

当然,您可以根据邮政编码的值进行过滤,返回与街道地址无关的元素。而且,还可以在单个查询中根据多个 xml(标准化越来越近了) 元素值进行过滤。下面的查询返回居住在纽约市具有特定邮政编码(10011)的地区或圣何塞(San Jose)任何地方的客户的电子邮件信息。

清单 12. 在 FLWOR 表达式中根据多个 xml(标准化越来越近了) 元素值过滤



xquery

for $y in db2-fn:xml(标准化越来越近了)column('CLIENTS.CONTACTINFO')/Client

where $y/Address/zip="10011" or $y/Address/city="San Jose"

return $y/email

注意,我们更改了 for 子句,从而将变量 $y 绑定到 Client 元素,而不是绑定到 Address 元素。这样一来便可以根据 Client 元素的一部分子树(Address)过滤该元素,而返回另一部分子树(email)。where 子句和 return 子句中的路径表达式必须相对被绑定到变量(这里是 $y)的元素来编写。

通过路径表达式可以更简单地表达相同的查询:

清单 13. 使用路径表达式根据多个 xml(标准化越来越近了) 元素值进行过滤



xquery

db2-fn:xml(标准化越来越近了)column('CLIENTS.CONTACTINFO')/Client[Address/zip="10011"

or Address/city="San Jose"]/email;

仔细观察该查询的两种不同形式,其中比较隐蔽的一点是,与 SQL 程序员的预期相比,返回的结果在两个方面存在不同之处:
  1. 返回的结果中不包含那些符合条件但是没有提供电子邮件地址的客户的 xml(标准化越来越近了) 数据。换句话说,如果有 1000 个客户居住在圣河塞或邮政编码为 10011 的地区,其中有 700 个客户提供了电子邮件地址,那么返回的将是这 700 个电子邮件地址。这是由于前面提到的 XQuery 与 SQL 之间存在的基本差异 —— XQuery 不使用 null。
  2. 您无法知道哪些电子邮件地址来自同一个 xml(标准化越来越近了) 文档。换句话说,如果有 700 个居住在圣河塞或邮政编码为 10011 的地区的客户,并且每个客户提供了两个电子邮件地址,那么返回的结果是 1400 个 email 元素组成的列表。您得到的不是 一个包含 700 个记录、每个记录由两个电子邮件地址组成的序列。
这两点在某些情况下是可以的,在另外一些情况下又可能不可取。例如,如果需要通过电子邮件将一个通知发送给每个符合条件的有记录的帐户,那么很容易在应用程序中对 xml(标准化越来越近了) 格式的客户电子邮件地址列表进行迭代。然而,如果对每个客户只发送一次通知,包括那些没有提供街道地址的客户,那么上述 XQuery 就不能满足要求了。

有多种方法来修改这个查询,使返回的结果以某种方式表示缺失的信息,并且在有多个电子邮件地址来自相同客户记录(即相同的 xml(标准化越来越近了) 文档)的情况下作出说明。让我们简要地探索一下其中一种方法。不过,如果只是要检索一个列表,其中对于每个符合条件的客户包含一个电子邮件地址,那么只需对之前查询中的 return 子句略作修改:

清单 14. 只检索每个客户的第一个 email 元素



xquery

for $y in db2-fn:xml(标准化越来越近了)column('CLIENTS.CONTACTINFO')/Client

where $y/Address/zip="10011" or $y/Address/city="San Jose"

return $y/email[1]

该查询导致 DB2 返回它在每个符合条件的 xml(标准化越来越近了) 文档(客户联系方式记录)中找到的第一个电子邮件元素。如果对于一个符合条件的客户,DB2 没有找到电子邮件地址,那么对于这个客户就不返回任何信息。

转换 xml(标准化越来越近了) 输出

XQuery 的一个强大的方面是可以将 xml(标准化越来越近了) 输出从一种格式转换成另一种格式。例如,可以使用 XQuery 检索所有或部分存储的 xml(标准化越来越近了) 文档,并将输出转换成 HTML,以便在 Web 浏览器中显示。下面 清单 15 中的查询检索客户的地址,按照邮政编码对结果排序,并将输出转换成 xml(标准化越来越近了) 元素,作为一个无序的 HTML 列表中的一部分:

清单 15. 查询 DB2 xml(标准化越来越近了) 数据并以 HTML 格式返回结果



xquery

<ul> {

for $y in db2-fn:xml(标准化越来越近了)column('CLIENTS.CONTACTINFO')/Client/Address

order by $y/zip

return <li>{$y}</li>

} </ul>

该查询首先以 xquery 关键字开头,告诉 DB2 解析器 XQuery 是顶层语言。第二行将表示无序列表的 HTML 标记(<ul>)包括在结果中。它还包含本查询中使用的一对花括号中的左括号。花括号指示 DB2 计算和处理其中的表达式,而不是将其当作文字字符串。

第三行对客户地址进行迭代,依次将变量 $y 绑定到每个 address 元素。第四行包括一个新的 order by 子句,指出结果必须按照客户邮政编码(绑定到 $y 的每个 address 元素的 zip 子元素)升序排列。return 子句表明 Address 元素在返回之前要用 HTML 列表 item 标记括起来。最后一行结束查询,并结束 HTML 无序列表标记。

输出将类似 清单 16 所示:

清单 16. 上述查询的示例 HTML 输出



<ul>

<li>

<Address>

<street>9407 Los Gatos Blvd.</street>

<city>Los Gatos</city>

<state>CA</state>

<zip>95032</zip>

</Address>

</li>

<li>

<Address>

<street>4209 El Camino Real</street>

<city>Mountain View</city>

<state>CA</state>

<zip>95033</zip>

</Address>

</li>

. . .

</ul>

我们来考虑之前遇到的一个话题:当需要在返回结果中表明缺失的值,以及表明单个 xml(标准化越来越近了) 文档(例如单个客户记录)包含重复的元素(例如多个 email 地址)时,如何编写 XQuery。一种方法是将返回的输出封装在一个新的 xml(标准化越来越近了) 元素中,如下面 清单 17 中的查询所示:

清单 17. 在 XQuery 结果中表明缺失的值和重复的元素



xquery

for $y in db2-fn:xml(标准化越来越近了)column('CLIENTS.CONTACTINFO')/Client

where $y/Address[zip="10011"] or $y/Address[city="San Jose"]

return <emailList> {$y/email} </emailList>

该查询将返回一个 “emailList” 元素序列,每个符合条件的客户记录对应一个元素。每个 emailList 元素将包含 e-mail 数据。如果 DB2 在客户的记录中只发现一个 e-mail 地址,它将返回那个元素和它的值。如果 DB2 发现多个 e-mail 地址,它将返回所有 e-mail 元素和它们的值。最后,如果 DB2 没有发现 e-mail 地址,那么它将返回一个空的 emailList 元素。因此,输出如下所示:

清单 18. 上述查询的示例输出



<emailList>

<email>love2shop@yahoo.com</email>

</emailList>

<emailList/>

<emailList>

<email>beatlesfan36@hotmail.com</email>

<email>lennonfan36@hotmail.com</email>

</emailList>

. . .

使用条件逻辑

XQuery 的 xml(标准化越来越近了) 输出转换功能可以与它内置的对条件逻辑的支持相结合,以减少应用程序代码的复杂性。“items” 表中包括一个 xml(标准化越来越近了) 列,该列包含客户对产品作出的评论。有些客户要求对他们的评论作出响应,对于这些用户,需要创建新的 “action” 元素,其中包含产品 ID、客户 ID 和评语,以便将这些信息发送给适当的个人进行处理。但是,那些不要求响应的评论在商业上也是非常重要的信息,您不想忽视它们。所以,创建一个 “info” 元素,其中只包含产品 ID 和评语。下面展示了如何使用 XQuery if-then-else 表达式来完成这项任务:

清单 19. 在 XQuery 中使用 “if-then-else” 表达式



xquery

for $y in db2-fn:xml(标准化越来越近了)column('ITEMS.COMMENTS')/Comments/Comment

return (

if ($y/ResponseRequested = 'Yes')

then <action>

{$y/ProductID,

$y/CustomerID,

$y/Message}

</action>

else ( <info>

{$y/ProductID,

$y/Message}

</info>

)

)

现在您应该对这个查询的大部分感到熟悉,所以我们只关注条件逻辑。if 子句判断一条给定评论的 ResponseRequested 子元素的值是否等于 “Yes”。如果是,那么执行 then 子句,导致 DB2 返回一个新元素(“action”),其中包含三个子元素:ProductID、CustomerID 和 Message。否则,执行 else 子句,DB2 返回一个 “info” 元素,其中只包含产品 ID 和评语数据。

使用 “let” 子句

您已经看到了如何使用 FLWOR 表达式的所有部分,除了一个部分:let 子句。该子句用于将一个值(可能包含一个由多项组成的列表)赋给一个变量,这个变量可以在 FLWOR 表达式的其他子句中使用。

假设您想得到一份列表,统计出每种产品收到的评论数量。那么可以使用以下查询:

清单 20. 使用 “let” 子句



xquery

for $p in distinct-values

(db2-fn:xml(标准化越来越近了)column('ITEMS.COMMENTS')/Comments/Comment/ProductID)

let $pc := db2-fn:xml(标准化越来越近了)column('ITEMS.COMMENTS')

/Comments/Comment[ProductID = $p]

return

<product>

<id> { $p } </id>

<comments> { count($pc) } </comments>

</product>

for 子句中的 distinct-values 函数返回一个列表,其中包含在 ITEMS 表的 COMMENTS 列中的所有 Comment 中发现的所有不同的 ProductID 值。for 子句依次将变量 $p 绑定到每个 ProductID 值。对于 $p 的每个值,let 子句再次扫描 ITEMS 列,并将变量 $pc 绑定到一个列表,列表中包含所有 ProductID 与 $p 中的 ProductID 相匹配的评论。return 子句为每个不同的 ProductID 值构造一个新的 “product” 元素。每个 “product” 元素包含两个子元素:一个包含 ProductID 值的 “id” 元素,和一个包含给定产品上所收到的评论的数量的 “comments” 元素。

这个例子查询的结果如下:

清单 21. 上述查询的示例输出



<product>

<id>3926</id>

<comments>28</comments>

</product>

<product>

<id>4097</id>

<comments>13</comments>

</product>

带嵌入式 SQL 的 XQueries

至此,您已经看到了如何编写 XQuery 来检索 xml(标准化越来越近了) 文档片段,创建新格式的 xml(标准化越来越近了) 输出,以及根据查询中指定的条件返回不同的输出。简言之,您已经学会了使用 XQuery 查询存储在 DB2 中的 xml(标准化越来越近了) 数据的几种方法。

显然,除了本文介绍的内容外,关于 XQuery 还有更多要学的东西。但是我们不能忽略了我们还没有讲到的一个大话题:如何在 XQuery 中嵌入 SQL。如果需要编写根据 xml(标准化越来越近了) 和非 xml(标准化越来越近了) 列的值过滤数据的查询,那么这样做很有用。

您可能还记得,文章 “用 SQL 查询 DB2 xml(标准化越来越近了) 数据” 描述了如何将简单的 XQuery 表达式嵌入在 SQL 语句中,以便完成这样的任务。这里,我们来看看如何反过来做:将 SQL 嵌入在 XQuery 中,从而根据传统的 SQL 数据值和特定的 xml(标准化越来越近了) 元素值对结果进行限制。

您可以使用 db2-fn:sqlquery 函数替代 db2-fn:xml(标准化越来越近了)column 函数,后者返回一个表的一个列中所有 xml(标准化越来越近了) 数据,而前者执行一个 SQL 查询,并且只返回所选择的数据。传递给 db2-fn:sqlquery 函数的 SQL 查询必须返回 xml(标准化越来越近了) 数据。然后 XQuery 可以进一步处理这种 xml(标准化越来越近了) 数据。

清单 22 中的查询检索关于评论的信息,评论所涉及的产品是建议零售价("srp")大于 $100 的产品,并且在评论中客户请求响应。您应该记得,价格数据存储在一个十进制数类型的 SQL 列中,而客户评论则存储为 xml(标准化越来越近了)。对于存储在数据库中的每条符合条件的评论,返回的数据(包括产品 ID、客户 ID 和客户评论)被包括在一个 xml(标准化越来越近了) “action” 元素中。

清单 22. 将 SQL 嵌入在 XQuery 中



xquery

for $y in

db2-fn:sqlquery('select comments from items where srp > 100')/Comments/Comment

where $y/ResponseRequested="Yes"

return (

<action>

{$y/ProductID,

$y/CustomerID,

$y/Message}

</action>

)

同样,这个查询的大部分对于您来说应该比较熟悉了,所以我们只关注这里出现的新函数:db2-fn:sqlquery。DB2 处理提供给该函数的 SQL SELECT 语句,以确定哪些行包含关于定价超过 $100 的产品的信息。存储在这些行中的文档作为一个路径表达式的输出,该路径表达式返回所有内嵌的 Comment 元素。该查询中随后的部分使用 XQuery where 子句进一步过滤返回的数据,并将选中的评论的一些部分转换成新的 xml(标准化越来越近了) 片段。

清楚这些之后,让我们考虑如何解决一个稍微不同的问题。假设您需要一份列表,其中包含居住在圣河塞的 “Gold” 客户的所有 e-mail 地址。而且,如果一个客户有多个 e-mail 地址,那么您希望将这些 e-mail 地址都包括在输出中,作为单个客户记录的一部分。最后,如果某个符合条件的 “Gold” 客户没有提供 e-mail 地址,那么需要检索他或她的邮递地址。清单 23 展示了编写该查询的一种方法:

清单 23. 将 SQL 嵌入在包含条件逻辑的 XQuery 中



xquery

for $y in

db2-fn:sqlquery('select contactinfo from clients where status=''Gold'' ')/Client

where $y/Address/city="San Jose"

return (

if ($y/email) then <emailList>{$y/email}</emailList>

else $y/Address

)

这个查询有两个方面要解释一下。首先,嵌入在第二行的 SELECT 语句包含一个基于 “status” 列的查询谓词,它将这个 VARCHAR 列与字符串 "Gold" 相比较。在 SQL 中,这样的字符串放在单引号里面。注意,虽然这个例子看上去使用了双引号,但实际上它是在比较值("Gold")前后使用了两个单引号。“额外” 的那个单引号是换码符。如果在基于字符串的查询谓词周围使用双引号,而不是单引号,就会收到语法错误。

此外,这个查询中的 return 子句包含一个条件逻辑,用于判断给定客户的记录中是否存在 e-mail 元素。如果存在,那么该查询将返回一个新的 “emailList” 元素,其中包含客户的所有 e-mail 地址(也就是那个客户的所有 e-mail 元素)。如果不存在,那么该查询将返回客户的邮递地址(也就是那个客户的 Address 元素)。

索引

最后,值得注意的是,您可以专门创建 xml(标准化越来越近了) 索引来加快对存储在 xml(标准化越来越近了) 列中的数据的访问速度。由于本文只是一篇介绍性的文章,而且样本数据偏小,因此这里不打算就此话题展开讨论。但是在生产环境中,定义适当的索引对于取得最佳性能是非常关键的。请参阅 参考资料 了解关于 DB2 新的索引技术的更多信息。

结束语

XQuery 与 SQL 之间有一些很大的不同点,本文谈到了其中的一些不同点。了解更多关于该语言的知识将有助于判断该语言在什么情况下对您的工作最有好处,并且有助于理解在什么情况下将 XQuery 与 SQL 相结合会比较有用。在将来的文章中,我们将深入研究另一个有趣的话题:如何开发利用 DB2 xml(标准化越来越近了) 功能的 Java 应用程序。本文提供了一个 简单的 Java 例子,其中描述了如何在 Java 应用程序中嵌入 XQuery。

Tags:使用 XQuery 查询

编辑录入:coldstar [复制链接] [打 印]
赞助商链接