|
以下是https://docs.oracle.com/cd/B28359_01/appdev.111/b28425/pipelined_example.htm#CHDHDHEE的确切实现 i- x, @0 L! J
7 z( x1 d4 V+ ]2 a假设我们具有以下表定义:9 W; j" A* m# q) a, v$ ?2 a* q
CREATE TABLE StockTable (
1 s* J% U: i. Z5 O# u0 l ticker VARCHAR(4),
0 k9 G8 e0 A- C" o+ a openprice NUMBER,
+ B& q* ~- F" m9 I closeprice NUMBER/ S' {( t) `! }* j+ T. J; B3 o
);$ ~' d, m% s2 U- h& V6 Z9 h; [5 o
然后,我们得到以下类型(作为对象的基本类型和作为表的类型):
* ?' P/ w7 O4 S5 U+ n& a- XCREATE TYPE TickerType AS OBJECT
! D& V+ n( Z6 T5 v: F: ?(
8 [8 _* u, q# g2 Q ticker VARCHAR2(4),1 p/ Y1 H4 W& ^7 W/ t
PriceType VARCHAR2(1),/ |7 z: q, e Y% n& h1 d
price NUMBER1 @: t* e6 H; `1 s' y" x7 }: s
);8 f8 r: s7 j, {6 ~
/
! @4 T- Q, O7 w2 n# Q4 {CREATE TYPE TickerTypeSet AS TABLE OF TickerType;8 E7 @) [! O) `7 n) a) T" K, C3 K
此外,我们还定义了ODCI类型及其在数据库中的SQL和Java存储过程中的实现:
5 J5 Z8 r2 O; S! W/ E6 H/ OSQL:- Z; x$ d2 Q! H% X8 q
CREATE OR REPLACE TYPE StockPivotImpl AS OBJECT0 ?8 A- G* E+ h; Q D. r
(/ E/ E6 ^7 U4 H g
key INTEGER,1 s) S$ T2 p+ e/ v- J5 n
STATIC FUNCTION ODCITableStart(sctx OUT StockPivotImpl, cur SYS_REFCURSOR)) a$ {+ N# K! W: g- s! {) ]
RETURN NUMBER7 l/ ]1 w& T# V) Z9 y
AS LANGUAGE JAVA
4 ^8 p1 [: M( D8 X& Z. r, a: @ NAME 'StockPivotImpl.ODCITableStart(oracle.sql.STRUCT[], java.sql.ResultSet) return java.math.BigDecimal',
& z2 p' s( S4 h, ~% V MEMBER FUNCTION ODCITableFetch(self IN OUT StockPivotImpl, nrows IN NUMBER,
& f# {0 c2 Z) E K outSet OUT TickerTypeSet) RETURN NUMBER' ^3 k" O* B) a% C# i& `6 E
AS LANGUAGE JAVA
~# @; B/ C( @; | NAME 'StockPivotImpl.ODCITableFetch(java.math.BigDecimal, oracle.sql.ARRAY[]) return java.math.BigDecimal',' k# \8 S3 Q/ _2 V. Z
MEMBER FUNCTION ODCITableClose(self IN StockPivotImpl) RETURN NUMBER
\# Z x" s+ U' v8 m$ h; k AS LANGUAGE JAVA
8 t% O4 f# a8 {0 N' r" S# B. S( e NAME 'StockPivotImpl.ODCITableClose() return java.math.BigDecimal'
' O5 ~& h0 d8 ~' u: j# n1 X);
% w9 C/ X9 n/ P/ @' @/
% J3 a& p( X; d0 Y0 c$ G$ dJava存储过程:" w$ H- [3 w, ?1 h4 q( s
import java.io.*;* b6 ?$ E1 h) w! g6 O( _+ d0 z5 E
import java.util.*;
+ l4 ~$ P1 H# Simport oracle.sql.*;, j$ l7 ]: g3 k1 T( T$ D! g
import java.sql.*;
: p. r3 G4 K f- b/ X j0 b; D8 Aimport java.math.BigDecimal;; [0 k: F" K1 ?
import oracle.CartridgeServices.*;+ n8 y5 F& @# e- U) i
// stored context type
1 l8 V: p7 F( m/ ]public class StoredCtx7 V% p# m; E& U! f* w$ X
{& {$ m2 d- [4 Y$ \8 a* P
ResultSet rset;
0 O4 S5 V% `" l. v; c4 T0 s public StoredCtx(ResultSet rs) { rset=rs; }: I( w) D" f7 K* m- C* i
}) ^& N& M8 L; G& E$ O! l: X
// implementation type+ h% `( K2 Q1 c" s4 N' H
public class StockPivotImpl implements SQLData
" P8 k- Z! u3 X. A{- {4 E) d% I/ Y- P0 O: |
private BigDecimal key;9 [$ X; g9 B2 W& s1 t1 C6 m
final static BigDecimal SUCCESS = new BigDecimal(0);( o6 s3 l+ s, c z6 L2 ~, w
final static BigDecimal ERROR = new BigDecimal(1);
9 |" m7 F0 M! h; ?5 m& ]9 _% | // Implement SQLData interface.
" ~# z5 K) p: M2 w& L String sql_type;# x3 m0 `* F7 }7 W
public String getSQLTypeName() throws SQLException # x( c3 k5 H: n3 _0 A
{. _; ]$ I" c) N/ H, w7 r
return sql_type;" D i/ T' u5 ?/ G
}
- ]0 K, J' h2 k, T% U public void readSQL(SQLInput stream, String typeName) throws SQLException # R% q6 `) ^2 d, w. W" D4 Z
{
0 o! d1 u, W3 o$ V9 ]" o& G sql_type = typeName;* y2 l4 @" l# k, x# h6 Y, ?- u8 Z" |
key = stream.readBigDecimal();
- n4 v A* f# z: ~3 s }
! g/ }; _9 E1 e$ j# {, n7 K public void writeSQL(SQLOutput stream) throws SQLException
1 B3 L2 }3 t q% F {. p9 Y+ e7 O% ~ C
stream.writeBigDecimal(key);' i* S, i$ {3 a% y* o; e* M1 T
}* `) c. d0 P& O+ e
// type methods implementing ODCITable interface1 D- S0 `2 e& y4 m* J; `6 L" E+ {3 \
static public BigDecimal ODCITableStart(STRUCT[] sctx,ResultSet rset)5 i# U) s8 r/ `7 |
throws SQLException
) p$ s1 m i. Z0 H! Y {- {- @- U0 p. V! L4 W+ {
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
0 S8 x) e$ S- O6 B4 x Z& X( s! l // create a stored context and store the result set in it* y8 t/ h- J% k7 ^
StoredCtx ctx=new StoredCtx(rset);# n: s& A3 |& }% ^; B+ V
// register stored context with cartridge services7 F. j4 U0 m3 G
int key;6 G8 Y8 z7 g6 _1 b
try {; k4 @! [ T$ d% o% Q) E4 l( D6 g
key = ContextManager.setContext(ctx);
. k6 _+ H% d, Y7 c: r" m! J2 ?9 } } catch (CountException ce) {
; V4 q7 }- Z5 u* a% e$ C3 S return ERROR;$ j+ U' R8 \0 t. j1 V3 M$ @
}$ ~& }+ d+ ~6 `3 u% J
// create a StockPivotImpl instance and store the key in it
7 s B$ c# a+ w# F2 H9 X Object[] impAttr = new Object[1];; I1 k9 R$ `. l z w. V
impAttr[0] = new BigDecimal(key); + M( w8 o, n7 A w5 ?$ k8 T
StructDescriptor sd = new StructDescriptor("STOCKPIVOTIMPL",conn);% B$ `% E0 n) [0 w. v3 | H0 b! [
sctx[0] = new STRUCT(sd,conn,impAttr);4 z) @4 T$ P- R& x: f
return SUCCESS;
* `: x$ _8 ?$ h; N0 H2 u* N }* f& ~% n0 T1 C& G4 h% z6 D
public BigDecimal ODCITableFetch(BigDecimal nrows, ARRAY[] outSet)& |4 @+ M C- [0 H0 h5 M( s
throws SQLException 3 o; `6 W( U U$ I, i D4 A3 C& S2 U
{
. l8 I Y$ M) k& R; t Connection conn = DriverManager.getConnection("jdbc:default:connection:");; V8 H+ q% S& @
// retrieve stored context using the key x1 E. M: `( h$ l
StoredCtx ctx;
6 _* ~( k! \% v2 d% J* V1 H8 m7 z) L, x try {' U! x4 C# q' R( d0 D# G. A8 v
ctx=(StoredCtx)ContextManager.getContext(key.intValue());
& L$ y4 y7 Q* M' l- E } catch (InvalidKeyException ik ) {' j/ X6 [0 d2 F/ e1 J+ P
return ERROR;7 L' y# ?1 c* z, a2 E8 [) h
}
' Q) }3 B l6 {( J // get the nrows parameter, but return up to 10 rows
+ U- i- [% H) S2 |0 N( g int nrowsval = nrows.intValue();
+ R* i( ]; z2 x, ]7 ^ if (nrowsval>10) nrowsval=10;/ k; i; `* u! ^ @: F
// create a vector for the fetched rows' A9 `$ O. G- p2 G5 a% F! e l
Vector v = new Vector(nrowsval);
$ E: t E k' \7 T1 O" I# U int i=0;
5 t7 w# U+ v, m; P! ^5 { t StructDescriptor outDesc =
& L- h7 b# q0 p5 u' o StructDescriptor.createDescriptor("TICKERTYPE", conn);
8 U/ H% f! l; Q9 C: U+ T Object[] out_attr = new Object[3];7 \1 E7 \' K \4 p7 d( C1 R
while(nrowsval>0 && ctx.rset.next()){' [) l; c, l5 S' }
out_attr[0] = (Object)ctx.rset.getString(1);$ H0 E. @0 q; M5 g m1 q$ P* p: v B
out_attr[1] = (Object)new String("O");9 I* W# x, Q" ^$ B; ]9 k! w
out_attr[2] = (Object)new BigDecimal(ctx.rset.getFloat(2));
0 l% Z1 K2 k# P0 o# ]$ N8 z v.add((Object)new STRUCT(outDesc, conn, out_attr));. J1 ?2 K0 b V- c6 ^* Y
out_attr[1] = (Object)new String("C");* [# V9 F4 d7 b5 R# y
out_attr[2] = (Object)new BigDecimal(ctx.rset.getFloat(3));
% j. _ A3 S+ V5 k) D" _) v/ }! t" A v.add((Object)new STRUCT(outDesc, conn, out_attr));
/ t' ~$ \* a; F: U: n i+=2;; Z3 E) h+ X8 W3 \
nrowsval-=2;' X. N4 u& [! h B( Y7 k
}6 D! ` Y5 @4 T9 L7 E, ?. j
// return if no rows found
; a+ |; i' S& q' F+ S% z if(i==0) return SUCCESS;
* N& _ e/ V0 k7 ? // create the output ARRAY using the vector b* @1 B! G9 Z. Z
Object out_arr[] = v.toArray();
/ v& G5 f' [8 `/ S4 [7 q: M5 ^ ArrayDescriptor ad = new ArrayDescriptor("TICKERTYPESET",conn);
2 h9 ^5 _) U- s) v7 } outSet[0] = new ARRAY(ad,conn,out_arr);+ A! c+ H5 n A- N e
return SUCCESS;2 i1 ?& s5 Q) o: B1 [; T( q) I
}; o' n y2 ~. b$ ?3 D9 X' h
public BigDecimal ODCITableClose() throws SQLException {
+ o% L/ m! t- X$ t // retrieve stored context using the key, and remove from ContextManager
! F/ }7 {) B9 o! W" S- B% H StoredCtx ctx;
( `$ O9 E. J9 a; [7 S+ u try {$ E. Q6 M9 s7 b0 X" g
ctx=(StoredCtx)ContextManager.clearContext(key.intValue());& f! n4 g- c' T' [5 B
} catch (InvalidKeyException ik ) {$ a: W: j% d' C5 S6 ]* k0 C
return ERROR;
X w: M0 P! O) M2 J# _1 h4 { }
' f7 T1 \9 L9 u6 I& D // close the result set
7 Q+ @; [! j: ^ C, Y: e Statement stmt = ctx.rset.getStatement();9 `" n s7 }/ }3 r7 q2 Z
ctx.rset.close();9 }4 A3 ]* `% m$ V; c& d
if(stmt!=null) stmt.close();' Q7 Q# @7 b6 T, E
return SUCCESS;
& J8 i/ G0 r" P1 e% l$ c- [ }
# a& o: U* H& q8 z}+ \8 u( }* C/ {0 q/ W
所有这些之后,为了拥有可用于创建上述表类型的表的 流水线函数 ,我们需要具有 ref游标 和 流水线函数本身
P$ u# k+ U: P$ [# u; D. S。我已将ref游标放入包中。1 ~# p( d8 w; D8 |
-- Define the ref cursor type
( Q' {" z: n3 [4 _ CREATE OR REPLACE PACKAGE refcur_pkg IS. b/ X7 J/ q" V$ E% u
TYPE refcur_t IS REF CURSOR RETURN StockTable%ROWTYPE;
+ [/ G* S3 i2 `9 O) W, I END refcur_pkg;, g. o( S6 A' F
/+ _+ n* v1 }! O r
-- Create table function+ n8 p X! J( y; ]3 C
CREATE OR REPLACE FUNCTION StockPivot(p refcur_pkg.refcur_t) RETURN TickerTypeSet9 L8 U( H8 F# y1 L
PIPELINED USING StockPivotImpl;, z) b5 ]' N0 @- ?
/
\. u# Z. D) B7 H! r我的问题是,如何调用StockPivot函数以执行JSP并显示所提到类型的表。! q7 U+ V$ \6 g5 v; P
我期望从模拟表的简单选择中得到一个结果:
% T- _' `* S/ p3 k-----------------------------
& l, e& n, t3 D7 K2 d7 K| column1 | column2 | ... | Q2 O+ Q3 H; b5 F( R0 P" j
|---------------------------|
: o6 q/ x, k @3 q| row_data1| row_data2| ... |0 ~/ w9 O3 |( W; @) l
| --------------------------|1 T d: l6 n4 P
|___________________________|4 ]. Q, S6 M/ R: m+ K- I2 E
我试图这样调用该函数,但是由于 明显的 原因(我们需要使用ref游标作为参数),它无法正常工作:0 ^) `8 c2 U. [3 |
SELECT * FROM TABLE(StockPivot());
! [: o( H' E2 K" F; ?8 I7 o先感谢您。7 ~7 U- M$ n/ K2 _8 \
+ | C }2 ~9 c7 Q* @解决方案: |
|