Oracle SQL - 如何使用 JSP 调用 ODCI 流水线函数
Oracle SQL - How can I call the ODCI pipelined function using JSP
以下是具体的实现
https://docs.oracle.com/cd/B28359_01/appdev.111/b28425/pipelined_example.htm#CHDHDHEE
假设我们有以下 table 定义:
CREATE TABLE StockTable (
ticker VARCHAR(4),
openprice NUMBER,
closeprice NUMBER
);
然后,我们得到了以下类型(一个基本类型作为对象,一个类型作为它的table):
CREATE TYPE TickerType AS OBJECT
(
ticker VARCHAR2(4),
PriceType VARCHAR2(1),
price NUMBER
);
/
CREATE TYPE TickerTypeSet AS TABLE OF TickerType;
另外,我们定义了一个 ODCI 类型,它在 SQL 和 Java 数据库中的存储过程中实现:
SQL:
CREATE OR REPLACE TYPE StockPivotImpl AS OBJECT
(
key INTEGER,
STATIC FUNCTION ODCITableStart(sctx OUT StockPivotImpl, cur SYS_REFCURSOR)
RETURN NUMBER
AS LANGUAGE JAVA
NAME 'StockPivotImpl.ODCITableStart(oracle.sql.STRUCT[], java.sql.ResultSet) return java.math.BigDecimal',
MEMBER FUNCTION ODCITableFetch(self IN OUT StockPivotImpl, nrows IN NUMBER,
outSet OUT TickerTypeSet) RETURN NUMBER
AS LANGUAGE JAVA
NAME 'StockPivotImpl.ODCITableFetch(java.math.BigDecimal, oracle.sql.ARRAY[]) return java.math.BigDecimal',
MEMBER FUNCTION ODCITableClose(self IN StockPivotImpl) RETURN NUMBER
AS LANGUAGE JAVA
NAME 'StockPivotImpl.ODCITableClose() return java.math.BigDecimal'
);
/
Java 存储过程:
import java.io.*;
import java.util.*;
import oracle.sql.*;
import java.sql.*;
import java.math.BigDecimal;
import oracle.CartridgeServices.*;
// stored context type
public class StoredCtx
{
ResultSet rset;
public StoredCtx(ResultSet rs) { rset=rs; }
}
// implementation type
public class StockPivotImpl implements SQLData
{
private BigDecimal key;
final static BigDecimal SUCCESS = new BigDecimal(0);
final static BigDecimal ERROR = new BigDecimal(1);
// Implement SQLData interface.
String sql_type;
public String getSQLTypeName() throws SQLException
{
return sql_type;
}
public void readSQL(SQLInput stream, String typeName) throws SQLException
{
sql_type = typeName;
key = stream.readBigDecimal();
}
public void writeSQL(SQLOutput stream) throws SQLException
{
stream.writeBigDecimal(key);
}
// type methods implementing ODCITable interface
static public BigDecimal ODCITableStart(STRUCT[] sctx,ResultSet rset)
throws SQLException
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
// create a stored context and store the result set in it
StoredCtx ctx=new StoredCtx(rset);
// register stored context with cartridge services
int key;
try {
key = ContextManager.setContext(ctx);
} catch (CountException ce) {
return ERROR;
}
// create a StockPivotImpl instance and store the key in it
Object[] impAttr = new Object[1];
impAttr[0] = new BigDecimal(key);
StructDescriptor sd = new StructDescriptor("STOCKPIVOTIMPL",conn);
sctx[0] = new STRUCT(sd,conn,impAttr);
return SUCCESS;
}
public BigDecimal ODCITableFetch(BigDecimal nrows, ARRAY[] outSet)
throws SQLException
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
// retrieve stored context using the key
StoredCtx ctx;
try {
ctx=(StoredCtx)ContextManager.getContext(key.intValue());
} catch (InvalidKeyException ik ) {
return ERROR;
}
// get the nrows parameter, but return up to 10 rows
int nrowsval = nrows.intValue();
if (nrowsval>10) nrowsval=10;
// create a vector for the fetched rows
Vector v = new Vector(nrowsval);
int i=0;
StructDescriptor outDesc =
StructDescriptor.createDescriptor("TICKERTYPE", conn);
Object[] out_attr = new Object[3];
while(nrowsval>0 && ctx.rset.next()){
out_attr[0] = (Object)ctx.rset.getString(1);
out_attr[1] = (Object)new String("O");
out_attr[2] = (Object)new BigDecimal(ctx.rset.getFloat(2));
v.add((Object)new STRUCT(outDesc, conn, out_attr));
out_attr[1] = (Object)new String("C");
out_attr[2] = (Object)new BigDecimal(ctx.rset.getFloat(3));
v.add((Object)new STRUCT(outDesc, conn, out_attr));
i+=2;
nrowsval-=2;
}
// return if no rows found
if(i==0) return SUCCESS;
// create the output ARRAY using the vector
Object out_arr[] = v.toArray();
ArrayDescriptor ad = new ArrayDescriptor("TICKERTYPESET",conn);
outSet[0] = new ARRAY(ad,conn,out_arr);
return SUCCESS;
}
public BigDecimal ODCITableClose() throws SQLException {
// retrieve stored context using the key, and remove from ContextManager
StoredCtx ctx;
try {
ctx=(StoredCtx)ContextManager.clearContext(key.intValue());
} catch (InvalidKeyException ik ) {
return ERROR;
}
// close the result set
Statement stmt = ctx.rset.getStatement();
ctx.rset.close();
if(stmt!=null) stmt.close();
return SUCCESS;
}
}
在所有这一切之后,为了拥有一个可用于创建上述 table 类型的 table 的流水线函数,我们需要一个 ref光标 和 流水线函数本身 。我已经将 ref 游标放入一个包中。
-- Define the ref cursor type
CREATE OR REPLACE PACKAGE refcur_pkg IS
TYPE refcur_t IS REF CURSOR RETURN StockTable%ROWTYPE;
END refcur_pkg;
/
-- Create table function
CREATE OR REPLACE FUNCTION StockPivot(p refcur_pkg.refcur_t) RETURN TickerTypeSet
PIPELINED USING StockPivotImpl;
/
我的问题是如何调用 StockPivot 函数以执行 JSP 并显示上述类型的 table。
我希望从模拟 table:
的简单 select 中得到结果
-----------------------------
| column1 | column2 | ... |
|---------------------------|
| row_data1| row_data2| ... |
| --------------------------|
|___________________________|
我试过这样调用该函数,但由于显而易见的原因(我们需要一个引用游标作为参数),它无法正常工作:
SELECT * FROM TABLE(StockPivot());
提前致谢。
选项 1 为 return 强引用游标创建函数。
create or replace function getCursor return refcur_pkg.refcur_t is
c_tmp refcur_pkg.refcur_t;
begin
open c_tmp for select * from StockTable;
return c_tmp;
end;
SELECT * FROM TABLE(StockPivot(getCursor()));
选项2。你可以试试游标表达式,应该也可以。 Cursor expression.
SELECT * FROM TABLE(StockPivot(Cursor(select * from StockTable)));
以下是具体的实现 https://docs.oracle.com/cd/B28359_01/appdev.111/b28425/pipelined_example.htm#CHDHDHEE
假设我们有以下 table 定义:
CREATE TABLE StockTable (
ticker VARCHAR(4),
openprice NUMBER,
closeprice NUMBER
);
然后,我们得到了以下类型(一个基本类型作为对象,一个类型作为它的table):
CREATE TYPE TickerType AS OBJECT
(
ticker VARCHAR2(4),
PriceType VARCHAR2(1),
price NUMBER
);
/
CREATE TYPE TickerTypeSet AS TABLE OF TickerType;
另外,我们定义了一个 ODCI 类型,它在 SQL 和 Java 数据库中的存储过程中实现:
SQL:
CREATE OR REPLACE TYPE StockPivotImpl AS OBJECT
(
key INTEGER,
STATIC FUNCTION ODCITableStart(sctx OUT StockPivotImpl, cur SYS_REFCURSOR)
RETURN NUMBER
AS LANGUAGE JAVA
NAME 'StockPivotImpl.ODCITableStart(oracle.sql.STRUCT[], java.sql.ResultSet) return java.math.BigDecimal',
MEMBER FUNCTION ODCITableFetch(self IN OUT StockPivotImpl, nrows IN NUMBER,
outSet OUT TickerTypeSet) RETURN NUMBER
AS LANGUAGE JAVA
NAME 'StockPivotImpl.ODCITableFetch(java.math.BigDecimal, oracle.sql.ARRAY[]) return java.math.BigDecimal',
MEMBER FUNCTION ODCITableClose(self IN StockPivotImpl) RETURN NUMBER
AS LANGUAGE JAVA
NAME 'StockPivotImpl.ODCITableClose() return java.math.BigDecimal'
);
/
Java 存储过程:
import java.io.*;
import java.util.*;
import oracle.sql.*;
import java.sql.*;
import java.math.BigDecimal;
import oracle.CartridgeServices.*;
// stored context type
public class StoredCtx
{
ResultSet rset;
public StoredCtx(ResultSet rs) { rset=rs; }
}
// implementation type
public class StockPivotImpl implements SQLData
{
private BigDecimal key;
final static BigDecimal SUCCESS = new BigDecimal(0);
final static BigDecimal ERROR = new BigDecimal(1);
// Implement SQLData interface.
String sql_type;
public String getSQLTypeName() throws SQLException
{
return sql_type;
}
public void readSQL(SQLInput stream, String typeName) throws SQLException
{
sql_type = typeName;
key = stream.readBigDecimal();
}
public void writeSQL(SQLOutput stream) throws SQLException
{
stream.writeBigDecimal(key);
}
// type methods implementing ODCITable interface
static public BigDecimal ODCITableStart(STRUCT[] sctx,ResultSet rset)
throws SQLException
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
// create a stored context and store the result set in it
StoredCtx ctx=new StoredCtx(rset);
// register stored context with cartridge services
int key;
try {
key = ContextManager.setContext(ctx);
} catch (CountException ce) {
return ERROR;
}
// create a StockPivotImpl instance and store the key in it
Object[] impAttr = new Object[1];
impAttr[0] = new BigDecimal(key);
StructDescriptor sd = new StructDescriptor("STOCKPIVOTIMPL",conn);
sctx[0] = new STRUCT(sd,conn,impAttr);
return SUCCESS;
}
public BigDecimal ODCITableFetch(BigDecimal nrows, ARRAY[] outSet)
throws SQLException
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
// retrieve stored context using the key
StoredCtx ctx;
try {
ctx=(StoredCtx)ContextManager.getContext(key.intValue());
} catch (InvalidKeyException ik ) {
return ERROR;
}
// get the nrows parameter, but return up to 10 rows
int nrowsval = nrows.intValue();
if (nrowsval>10) nrowsval=10;
// create a vector for the fetched rows
Vector v = new Vector(nrowsval);
int i=0;
StructDescriptor outDesc =
StructDescriptor.createDescriptor("TICKERTYPE", conn);
Object[] out_attr = new Object[3];
while(nrowsval>0 && ctx.rset.next()){
out_attr[0] = (Object)ctx.rset.getString(1);
out_attr[1] = (Object)new String("O");
out_attr[2] = (Object)new BigDecimal(ctx.rset.getFloat(2));
v.add((Object)new STRUCT(outDesc, conn, out_attr));
out_attr[1] = (Object)new String("C");
out_attr[2] = (Object)new BigDecimal(ctx.rset.getFloat(3));
v.add((Object)new STRUCT(outDesc, conn, out_attr));
i+=2;
nrowsval-=2;
}
// return if no rows found
if(i==0) return SUCCESS;
// create the output ARRAY using the vector
Object out_arr[] = v.toArray();
ArrayDescriptor ad = new ArrayDescriptor("TICKERTYPESET",conn);
outSet[0] = new ARRAY(ad,conn,out_arr);
return SUCCESS;
}
public BigDecimal ODCITableClose() throws SQLException {
// retrieve stored context using the key, and remove from ContextManager
StoredCtx ctx;
try {
ctx=(StoredCtx)ContextManager.clearContext(key.intValue());
} catch (InvalidKeyException ik ) {
return ERROR;
}
// close the result set
Statement stmt = ctx.rset.getStatement();
ctx.rset.close();
if(stmt!=null) stmt.close();
return SUCCESS;
}
}
在所有这一切之后,为了拥有一个可用于创建上述 table 类型的 table 的流水线函数,我们需要一个 ref光标 和 流水线函数本身 。我已经将 ref 游标放入一个包中。
-- Define the ref cursor type
CREATE OR REPLACE PACKAGE refcur_pkg IS
TYPE refcur_t IS REF CURSOR RETURN StockTable%ROWTYPE;
END refcur_pkg;
/
-- Create table function
CREATE OR REPLACE FUNCTION StockPivot(p refcur_pkg.refcur_t) RETURN TickerTypeSet
PIPELINED USING StockPivotImpl;
/
我的问题是如何调用 StockPivot 函数以执行 JSP 并显示上述类型的 table。
我希望从模拟 table:
的简单 select 中得到结果-----------------------------
| column1 | column2 | ... |
|---------------------------|
| row_data1| row_data2| ... |
| --------------------------|
|___________________________|
我试过这样调用该函数,但由于显而易见的原因(我们需要一个引用游标作为参数),它无法正常工作:
SELECT * FROM TABLE(StockPivot());
提前致谢。
选项 1 为 return 强引用游标创建函数。
create or replace function getCursor return refcur_pkg.refcur_t is
c_tmp refcur_pkg.refcur_t;
begin
open c_tmp for select * from StockTable;
return c_tmp;
end;
SELECT * FROM TABLE(StockPivot(getCursor()));
选项2。你可以试试游标表达式,应该也可以。 Cursor expression.
SELECT * FROM TABLE(StockPivot(Cursor(select * from StockTable)));