Oracle 85*准备步骤。初始化我们的类型。 86 */ 87静态功能ODCITableprepare(sctx输出动态管道, 88 sys.odcitabFunsfo中的tf_信息, 瓦查尔89 stmt(2) 90返回号码 91是 92 93/*变量*/
85*准备步骤。初始化我们的类型。 86 */ 87静态功能ODCITableprepare(sctx输出动态管道, 88 sys.odcitabFunsfo中的tf_信息, 瓦查尔89 stmt(2) 90返回号码 91是 92 93/*变量*/ 94--元数据。 95 r_meta pkg_pipeline.anytype_metadata_rec; 96 97开始 98 99 r_meta.typecode:=tf_info.rettype.getattreleminfo( 100 1,r_元精度,r_元刻度,r_元长度, 101 r_meta.csid,r_meta.csfrm,r_meta.type,r_meta.name 102 ); 103 104 sctx:=dyn_管道(r_元类型); 105返回odciconst.success; 106 107结束; 108 109 110 /* 111*开始步骤。这是我们在从中提取之前执行游标的位置。 112 */ 113静态功能ODCITablestart(sctx输入输出动态管线, 瓦查尔114 stmt(2) 115返回号码 116是 117 118/*变量*/ 119 r_meta pkg_pipeline.anytype_metadata_rec; 120 v_sql varchar2(32767); 121开始 122 123 v_sql:=replace(stmt,;,null); 124 pkg_pipeline.r_sql.cursor:=dbms_sql.open_cursor; 125 dbms_sql.parse(pkg_pipeline.r_sql.cursor、v_sql、dbms_sql.native); 126 dbms_sql.description_columns2(pkg_pipeline.r_sql.cursor, 127 pkg_pipeline.r_sql.column_cnt, 128 pkg_pipeline.r_sql.description); 129 130--定义找到的所有列,让Oracle知道数据类型。 131用于1..pkg_pipeline.r_sql.column_cnt中的i 132环路 133 134 r_meta.typecode:=sctx.atype.GetAttrElemInfo( 135 i,r_元精度,r_元刻度,r_元长度, 136 r_meta.csid,r_meta.csfrm,r_meta.type,r_meta.name 137 ); 138 139案例r_元类型代码 140当dbms_types.typecode_varchar2 那么 142 dbms_sql.define_列(pkg_pipeline.r_sql.cursor,i',,32767); 143当dbms_类型.typecode_编号 144那么 145 dbms_sql.define_列(pkg_pipeline.r_sql.cursor,i,cast(null为数字)); 146当dbms_types.typecode_date 147那么 148 dbms_sql.define_列(pkg_pipeline.r_sql.cursor,i,cast(null as date)); 149当dbms_types.typecode_原始时 150那么 151 dbms_sql.define_column_raw(pkg_pipeline.r_sql.cursor,i,cast(null为raw),r_meta.length); 152当dbms_types.typecode_时间戳 那么 154 dbms_sql.define_列(pkg_pipeline.r_sql.cursor,i,cast(null作为时间戳)); 155当dbms_types.typecode_timestamp_tz 那么 157 dbms_sql.define_列(pkg_pipeline.r_sql.cursor,i,cast(null为带时区的时间戳)); 158当dbms_types.typecode_timestamp_ltz 159那么 160 dbms_sql.define_列(pkg_pipeline.r_sql.cursor,i,cast(null为带有本地时区的时间戳)); 161当dbms_types.typecode_interval_ym 162那么 163 dbms_sql.define_列(pkg_pipeline.r_sql.cursor,i,cast(null为间隔年到月)); 164当dbms_type.typecode_interval_ds 那么 166 dbms_sql.define_列(pkg_pipeline.r_sql.cursor,i,cast(null为间隔日到秒)); 167当dbms_types.typecode_clob 168那么 169案例包装管道.r\U sql.说明(一).列类型 170时8分 171那么 172 dbms_sql.define_column_long(pkg_pipeline.r_sql.cursor,i); 173其他 174 dbms_sql.define_列(pkg_pipeline.r_sql.cursor,i,cast(null为clob)); 175端盒; 176例终末病例; 177端环; 178 179——执行SQL。 180 pkg_pipeline.r_sql.execute:=dbms_sql.execute(pkg_pipeline.r_sql.cursor); 181 182返回odciconst.success; 183 184结束ODC启动; 185 186 187 /* 188*提取步骤。 189 */ 190成员函数ODCITablefetch(自输入输出动态管道, 191挪威卢比, 192 rws输出(数据集) 193报税号码 194是 195 196/*变量*/ 197—保存值的缓冲区。 198 v_vc_col varchar2(32767); 199 v_num_col编号; 200 v_日期_col日期; 201 v_raw_col raw(32767); 202 v_原始错误号; 203 v_原始长度整数; 204 v_int_d_col间隔日至秒; 205 v_int_ym_col年至月间隔; 206 v_ts_col时间戳; 207 v_tstz_col带时区的时间戳; 208 v_tsltz_col带有本地时区的时间戳; 209 v_clob_col clob; 210 v_clob_偏移整数:=0; 211 v_clob_len整数; 212——元数据 213 r_meta pkg_pipeline.anytype_metadata_rec; 214 215开始 216 217如果dbms_sql.fetch_行(pkg_pipeline.r_sql.cursor)>0 218那么 219 220——描述以获取列的数量和类型。 221 r_meta.typecode:=self.atype.getinfo( 222 r_元精度,r_元刻度,r_元长度, 223 r_meta.csid,r_meta.csfrm,r_meta.schema, 224 r_meta.name、r_meta.version、r_meta.attr_cnt 225 ); 226 227 anydataset.begincreate(dbms_types.typecode_对象,self.atype,rws); 228 rws.addinstance(); 229 rws.分段(); 230 231——循环通过每列提取值。 232用于1..pkg_pipeline.r_sql.column_cnt中的i 233环路 234 235 r_meta.typecode:=self.atype.getattreleminfo( 236 i,r_元精度,r_元刻度,r_元长度, 237 r_meta.csid,r_Oracle 85*准备步骤。初始化我们的类型。 86 */ 87静态功能ODCITableprepare(sctx输出动态管道, 88 sys.odcitabFunsfo中的tf_信息, 瓦查尔89 stmt(2) 90返回号码 91是 92 93/*变量*/,oracle,oracle11g,Oracle,Oracle11g,85*准备步骤。初始化我们的类型。 86 */ 87静态功能ODCITableprepare(sctx输出动态管道, 88 sys.odcitabFunsfo中的tf_信息, 瓦查尔89 stmt(2) 90返回号码 91是 92 93/*变量*/ 94--元数据。 95 r_meta pkg_pipeline.anytype_metadata_rec; 96 97开始 98 99 r_meta.typecode:=tf_info.rettype.getattreleminfo( 100
select * from table(querydb('select * from dual'))
select * from (select * from dual)
declare
subQuery varchar2(1000);
mainQuery varchar2(1000) := 'select * from (';
type myRefCursor is ref cursor;
myResultset myRefCursor;
myField1 FIELDTYPE;
...
myFieldN FIELDTYPE;
begin
-- Generate this dynamically
subQuery := 'select * from dual';
-- Create main query and open cursor
mainQuery := mainQuery || subQuery || ')';
open myResultset for mainQuery;
-- Loop through records
loop
fetch myResultset into myField1, ..., myFieldN;
exit when myResultset%NOTFOUND;
-- Do something with the record data
dbms_output.put_line(myField1 || ' ... ' || myFieldN);
end loop;
close myResultset;
end;
/
myRecord someTable%ROWTYPE;
fetch myResultset into myRecord;
SQL> create type dyn_pipeline as object
2 (
3 atype anytype,
4
5 static function ODCITableDescribe(rtype out anytype,
6 stmt in varchar2)
7 return number,
8
9 static function ODCITablePrepare(sctx out dyn_pipeline,
10 tf_info in sys.ODCITabfuncinfo,
11 stmt in varchar2)
12 return number,
13
14 static function ODCITableStart(sctx in out dyn_pipeline,
15 stmt in varchar2)
16 return number,
17
18 member function ODCITablefetch(self in out dyn_pipeline,
19 nrows in number,
20 rws out anydataset)
21 return number,
22
23 member function ODCITableClose(self in dyn_pipeline)
24 return number
25 );
26 /
SQL> create package pkg_pipeline
2 as
3
4 /*
5 * Global Types
6 */
7 -- Describe array.
8 type dynamic_sql_rec is record(cursor integer,
9 column_cnt pls_integer,
10 description dbms_sql.desc_tab2,
11 execute integer);
12 -- Meta data for the ANYTYPE.
13 type anytype_metadata_rec is record(precision pls_integer,
14 scale pls_integer,
15 length pls_integer,
16 csid pls_integer,
17 csfrm pls_integer,
18 schema varchar2(30),
19 type anytype,
20 name varchar2(30),
21 version varchar2(30),
22 attr_cnt pls_integer,
23 attr_type anytype,
24 attr_name varchar2(128),
25 typecode pls_integer);
26
27
28 /*
29 * Global Variables
30 */
31 -- SQL descriptor.
32 r_sql dynamic_sql_rec;
33
34 /*
35 * function will run the given SQL
36 */
37 function querydb(p_stmt in varchar2)
38 return anydataset pipelined using dyn_pipeline;
39
40 end pkg_pipeline;
41 /
Package created.
SQL> create type body dyn_pipeline
2 as
3
4 /*
5 * DESC step. this will be called at hard parse and will create
6 * a physical type in the DB Schema based on the select columns.
7 */
8 static function ODCITableDescribe(rtype out anytype,
9 stmt in varchar2)
10 return number
11 is
12
13 /* Variables */
14 -- Type to hold the dbms_sql info (description)
15 r_sql pkg_pipeline.dynamic_sql_rec;
16 -- Type to create (has all the columns) of the sql query.
17 t_anyt anytype;
18 -- SQL query that will be made up from the 2 passed in queries.
19 v_sql varchar2(32767);
20
21 begin
22
23 /*
24 * Parse the SQL and describe its format and structure.
25 */
26 v_sql := replace(stmt, ';', null);
27
28 -- open, parse and discover all info about this SQL.
29 r_sql.cursor := dbms_sql.open_cursor;
30 dbms_sql.parse( r_sql.cursor, v_sql, dbms_sql.native );
31 dbms_sql.describe_columns2( r_sql.cursor, r_sql.column_cnt, r_sql.description );
32 dbms_sql.close_cursor( r_sql.cursor );
33
34 -- Start to create the physical type.
35 anytype.BeginCreate( DBMS_TYPES.TYPECODE_OBJECT, t_anyt );
36
37 -- Loop through each attribute and add to the type.
38 for i in 1 .. r_sql.column_cnt
39 loop
40
41 t_anyt.AddAttr(r_sql.description(i).col_name,
42 case
43 when r_sql.description(i).col_type in (1,96,11,208)
44 then dbms_types.typecode_varchar2
45 when r_sql.description(i).col_type = 2
46 then dbms_types.typecode_number
47 when r_sql.description(i).col_type in (8,112)
48 then dbms_types.typecode_clob
49 when r_sql.description(i).col_type = 12
50 then dbms_types.typecode_date
51 when r_sql.description(i).col_type = 23
52 then dbms_types.typecode_raw
53 when r_sql.description(i).col_type = 180
54 then dbms_types.typecode_timestamp
55 when r_sql.description(i).col_type = 181
56 then dbms_types.typecode_timestamp_tz
57 when r_sql.description(i).col_type = 182
58 then dbms_types.typecode_interval_ym
59 when r_sql.description(i).col_type = 183
60 then dbms_types.typecode_interval_ds
61 when r_sql.description(i).col_type = 231
62 then dbms_types.typecode_timestamp_ltz
63 end,
64 r_sql.description(i).col_precision,
65 r_sql.description(i).col_scale,
66 r_sql.description(i).col_max_len,
67 r_sql.description(i).col_charsetid,
68 r_sql.description(i).col_charsetform );
69 end loop;
70
71 t_anyt.EndCreate;
72
73 -- set the output type to our built type.
74 ANYTYPE.BeginCreate(dbms_types.TYPECODE_TABLE, rtype);
75 rtype.SetInfo(null, null, null, null, null, t_anyt,
76 dbms_types.TYPECODE_OBJECT, 0);
77 rtype.EndCreate();
78
79 return ODCIConst.Success;
80
81 end ODCITableDescribe;
82
83
84 /*
85 * PREPARE step. Initialise our type.
86 */
87 static function ODCITableprepare(sctx out dyn_pipeline,
88 tf_info in sys.ODCITabfuncinfo,
89 stmt in varchar2)
90 return number
91 is
92
93 /* Variables */
94 -- Meta data.
95 r_meta pkg_pipeline.anytype_metadata_rec;
96
97 begin
98
99 r_meta.typecode := tf_info.rettype.getattreleminfo(
100 1, r_meta.precision, r_meta.scale, r_meta.length,
101 r_meta.csid, r_meta.csfrm, r_meta.type, r_meta.name
102 );
103
104 sctx := dyn_pipeline(r_meta.type);
105 return odciconst.success;
106
107 end;
108
109
110 /*
111 * START step. this is where we execute the cursor prior to fetching from it.
112 */
113 static function ODCITablestart(sctx in out dyn_pipeline,
114 stmt in varchar2)
115 return number
116 is
117
118 /* Variables */
119 r_meta pkg_pipeline.anytype_metadata_rec;
120 v_sql varchar2(32767);
121 begin
122
123 v_sql := replace(stmt, ';', null);
124 pkg_pipeline.r_sql.cursor := dbms_sql.open_cursor;
125 dbms_sql.parse(pkg_pipeline.r_sql.cursor, v_sql, dbms_sql.native);
126 dbms_sql.describe_columns2(pkg_pipeline.r_sql.cursor,
127 pkg_pipeline.r_sql.column_cnt,
128 pkg_pipeline.r_sql.description);
129
130 -- define all the columns found to let Oracle know the datatypes.
131 for i in 1..pkg_pipeline.r_sql.column_cnt
132 loop
133
134 r_meta.typecode := sctx.atype.GetAttrElemInfo(
135 i, r_meta.precision, r_meta.scale, r_meta.length,
136 r_meta.csid, r_meta.csfrm, r_meta.type, r_meta.name
137 );
138
139 case r_meta.typecode
140 when dbms_types.typecode_varchar2
141 then
142 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, '', 32767);
143 when dbms_types.typecode_number
144 then
145 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as number));
146 when dbms_types.typecode_date
147 then
148 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as date));
149 when dbms_types.typecode_raw
150 then
151 dbms_sql.define_column_raw(pkg_pipeline.r_sql.cursor, i, cast(null as raw), r_meta.length);
152 when dbms_types.typecode_timestamp
153 then
154 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as timestamp));
155 when dbms_types.typecode_timestamp_tz
156 then
157 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as timestamp with time zone));
158 when dbms_types.typecode_timestamp_ltz
159 then
160 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as timestamp with local time zone));
161 when dbms_types.typecode_interval_ym
162 then
163 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as interval year to month));
164 when dbms_types.typecode_interval_ds
165 then
166 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as interval day to second));
167 when dbms_types.typecode_clob
168 then
169 case pkg_pipeline.r_sql.description(i).col_type
170 when 8
171 then
172 dbms_sql.define_column_long(pkg_pipeline.r_sql.cursor, i);
173 else
174 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as clob));
175 end case;
176 end case;
177 end loop;
178
179 -- execute the SQL.
180 pkg_pipeline.r_sql.execute := dbms_sql.execute(pkg_pipeline.r_sql.cursor);
181
182 return odciconst.success;
183
184 end ODCITablestart;
185
186
187 /*
188 * FETCH step.
189 */
190 member function ODCITablefetch(self in out dyn_pipeline,
191 nrows in number,
192 rws out anydataset)
193 return number
194 is
195
196 /* Variables */
197 -- Buffers to hold values.
198 v_vc_col varchar2(32767);
199 v_num_col number;
200 v_date_col date;
201 v_raw_col raw(32767);
202 v_raw_error number;
203 v_raw_len integer;
204 v_int_ds_col interval day to second;
205 v_int_ym_col interval year to month;
206 v_ts_col timestamp;
207 v_tstz_col timestamp with time zone;
208 v_tsltz_col timestamp with local time zone;
209 v_clob_col clob;
210 v_clob_offset integer := 0;
211 v_clob_len integer;
212 -- Metadata
213 r_meta pkg_pipeline.anytype_metadata_rec;
214
215 begin
216
217 if dbms_sql.fetch_rows( pkg_pipeline.r_sql.cursor ) > 0
218 then
219
220 -- Describe to get number and types of columns.
221 r_meta.typecode := self.atype.getinfo(
222 r_meta.precision, r_meta.scale, r_meta.length,
223 r_meta.csid, r_meta.csfrm, r_meta.schema,
224 r_meta.name, r_meta.version, r_meta.attr_cnt
225 );
226
227 anydataset.begincreate(dbms_types.typecode_object, self.atype, rws);
228 rws.addinstance();
229 rws.piecewise();
230
231 -- loop through each column extracting value.
232 for i in 1..pkg_pipeline.r_sql.column_cnt
233 loop
234
235 r_meta.typecode := self.atype.getattreleminfo(
236 i, r_meta.precision, r_meta.scale, r_meta.length,
237 r_meta.csid, r_meta.csfrm, r_meta.attr_type,
238 r_meta.attr_name
239 );
240
241 case r_meta.typecode
242 when dbms_types.typecode_varchar2
243 then
244 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_vc_col);
245 rws.setvarchar2(v_vc_col);
246 when dbms_types.typecode_number
247 then
248 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_num_col);
249 rws.setnumber(v_num_col);
250 when dbms_types.typecode_date
251 then
252 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_date_col);
253 rws.setdate(v_date_col);
254 when dbms_types.typecode_raw
255 then
256 dbms_sql.column_value_raw(pkg_pipeline.r_sql.cursor, i, v_raw_col,
257 v_raw_error, v_raw_len);
258 rws.setraw(v_raw_col);
259 when dbms_types.typecode_interval_ds
260 then
261 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_int_ds_col);
262 rws.setintervalds(v_int_ds_col);
263 when dbms_types.typecode_interval_ym
264 then
265 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_int_ym_col);
266 rws.setintervalym(v_int_ym_col);
267 when dbms_types.typecode_timestamp
268 then
269 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_ts_col);
270 rws.settimestamp(v_ts_col);
271 when dbms_types.typecode_timestamp_tz
272 then
273 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_tstz_col);
274 rws.settimestamptz(v_tstz_col);
275 when dbms_types.typecode_timestamp_ltz
276 then
277 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_tsltz_col);
278 rws.settimestampltz(v_tsltz_col);
279 when dbms_types.typecode_clob
280 then
281 case pkg_pipeline.r_sql.description(i).col_type
282 when 8
283 then
284 loop
285 dbms_sql.column_value_long(pkg_pipeline.r_sql.cursor, i, 32767, v_clob_offset,
286 v_vc_col, v_clob_len);
287 v_clob_col := v_clob_col || v_vc_col;
288 v_clob_offset := v_clob_offset + 32767;
289 exit when v_clob_len < 32767;
290 end loop;
291 else
292 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_clob_col);
293 end case;
294 rws.setclob(v_clob_col);
295 end case;
296 end loop;
297
298 rws.endcreate();
299
300 end if;
301
302 return ODCIConst.Success;
303
304 end;
305
306 /*
307 * CLOSE step. close the cursor.
308 */
309 member function ODCITableClose(self in dyn_pipeline)
310 return number
311 is
312
313
314 begin
315 dbms_sql.close_cursor( pkg_pipeline.r_sql.cursor );
316 pkg_pipeline.r_sql := null;
317 return odciconst.success;
318 end ODCITableClose;
319
320 end;
321 /
Type body created.
SQL> select * from table(pkg_pipeline.querydb('select * from dual'));
D
-
X
SQL> select * from table(pkg_pipeline.querydb('select * from v$mystat where rownum <= 2'));
SID STATISTIC# VALUE
---------- ---------- ----------
230 0 1
230 1 1