oracle – 从函数返回结果集

前端之家收集整理的这篇文章主要介绍了oracle – 从函数返回结果集前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我需要从函数返回结果集并使用此结果集,就像使用普通表一样.

所以我需要以下内容

  1. select * from table(querydb('select * from dual'))

querydb函数应该返回传递给它的查询的结果集.

可以在oracle中实现吗?

将不胜感激任何信息.

如果需要结果集,并且ref游标不适用于名为sys.anydataset的数据类型.即你想要的是一个 pipelined function,但当然有一个常规的流水线功能,你需要定义输出结构,在你的情况下,它不是静态的.

输入anydataset.这种类型允许我们动态地动态生成类型(仅在硬解析时),以允许我们定义具有不同输出的流水线函数.

不幸的是,编码有点复杂.

首先,我们定义一个类型来处理传入的sql语句.

  1. sql> create type dyn_pipeline as object
  2. 2 (
  3. 3 atype anytype,4
  4. 5 static function ODCITableDescribe(rtype out anytype,6 stmt in varchar2)
  5. 7 return number,8
  6. 9 static function ODCITablePrepare(sctx out dyn_pipeline,10 tf_info in sys.ODCITabfuncinfo,11 stmt in varchar2)
  7. 12 return number,13
  8. 14 static function ODCITableStart(sctx in out dyn_pipeline,15 stmt in varchar2)
  9. 16 return number,17
  10. 18 member function ODCITablefetch(self in out dyn_pipeline,19 nrows in number,20 rws out anydataset)
  11. 21 return number,22
  12. 23 member function ODCITableClose(self in dyn_pipeline)
  13. 24 return number
  14. 25 );
  15. 26 /

接下来,我们创建一个基本上是你的querydb函数调用的软件包规范:

  1. sql> create package pkg_pipeline
  2. 2 as
  3. 3
  4. 4 /*
  5. 5 * Global Types
  6. 6 */
  7. 7 -- Describe array.
  8. 8 type dynamic_sql_rec is record(cursor integer,9 column_cnt pls_integer,10 description dbms_sql.desc_tab2,11 execute integer);
  9. 12 -- Meta data for the ANYTYPE.
  10. 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);
  11. 26
  12. 27
  13. 28 /*
  14. 29 * Global Variables
  15. 30 */
  16. 31 -- sql descriptor.
  17. 32 r_sql dynamic_sql_rec;
  18. 33
  19. 34 /*
  20. 35 * function will run the given sql
  21. 36 */
  22. 37 function querydb(p_stmt in varchar2)
  23. 38 return anydataset pipelined using dyn_pipeline;
  24. 39
  25. 40 end pkg_pipeline;
  26. 41 /
  27.  
  28. Package created.

那里的类​​型只包含一些关于sql结构本身的信息(我们将使用DBMS_sql来描述输入sql,因为它具有从任何给定的sql语句中获取列数,数据类型等的函数.

主要类型主体是处理发生的位置:

  1. sql> create type body dyn_pipeline
  2. 2 as
  3. 3
  4. 4 /*
  5. 5 * DESC step. this will be called at hard parse and will create
  6. 6 * a physical type in the DB Schema based on the select columns.
  7. 7 */
  8. 8 static function ODCITableDescribe(rtype out anytype,9 stmt in varchar2)
  9. 10 return number
  10. 11 is
  11. 12
  12. 13 /* Variables */
  13. 14 -- Type to hold the dbms_sql info (description)
  14. 15 r_sql pkg_pipeline.dynamic_sql_rec;
  15. 16 -- Type to create (has all the columns) of the sql query.
  16. 17 t_anyt anytype;
  17. 18 -- sql query that will be made up from the 2 passed in queries.
  18. 19 v_sql varchar2(32767);
  19. 20
  20. 21 begin
  21. 22
  22. 23 /*
  23. 24 * Parse the sql and describe its format and structure.
  24. 25 */
  25. 26 v_sql := replace(stmt,';',null);
  26. 27
  27. 28 -- open,parse and discover all info about this sql.
  28. 29 r_sql.cursor := dbms_sql.open_cursor;
  29. 30 dbms_sql.parse( r_sql.cursor,v_sql,dbms_sql.native );
  30. 31 dbms_sql.describe_columns2( r_sql.cursor,r_sql.column_cnt,r_sql.description );
  31. 32 dbms_sql.close_cursor( r_sql.cursor );
  32. 33
  33. 34 -- Start to create the physical type.
  34. 35 anytype.BeginCreate( DBMS_TYPES.TYPECODE_OBJECT,t_anyt );
  35. 36
  36. 37 -- Loop through each attribute and add to the type.
  37. 38 for i in 1 .. r_sql.column_cnt
  38. 39 loop
  39. 40
  40. 41 t_anyt.AddAttr(r_sql.description(i).col_name,42 case
  41. 43 when r_sql.description(i).col_type in (1,96,11,208)
  42. 44 then dbms_types.typecode_varchar2
  43. 45 when r_sql.description(i).col_type = 2
  44. 46 then dbms_types.typecode_number
  45. 47 when r_sql.description(i).col_type in (8,112)
  46. 48 then dbms_types.typecode_clob
  47. 49 when r_sql.description(i).col_type = 12
  48. 50 then dbms_types.typecode_date
  49. 51 when r_sql.description(i).col_type = 23
  50. 52 then dbms_types.typecode_raw
  51. 53 when r_sql.description(i).col_type = 180
  52. 54 then dbms_types.typecode_timestamp
  53. 55 when r_sql.description(i).col_type = 181
  54. 56 then dbms_types.typecode_timestamp_tz
  55. 57 when r_sql.description(i).col_type = 182
  56. 58 then dbms_types.typecode_interval_ym
  57. 59 when r_sql.description(i).col_type = 183
  58. 60 then dbms_types.typecode_interval_ds
  59. 61 when r_sql.description(i).col_type = 231
  60. 62 then dbms_types.typecode_timestamp_ltz
  61. 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 );
  62. 69 end loop;
  63. 70
  64. 71 t_anyt.EndCreate;
  65. 72
  66. 73 -- set the output type to our built type.
  67. 74 ANYTYPE.BeginCreate(dbms_types.TYPECODE_TABLE,rtype);
  68. 75 rtype.SetInfo(null,null,t_anyt,76 dbms_types.TYPECODE_OBJECT,0);
  69. 77 rtype.EndCreate();
  70. 78
  71. 79 return ODCIConst.Success;
  72. 80
  73. 81 end ODCITableDescribe;
  74. 82
  75. 83
  76. 84 /*
  77. 85 * PREPARE step. Initialise our type.
  78. 86 */
  79. 87 static function ODCITableprepare(sctx out dyn_pipeline,88 tf_info in sys.ODCITabfuncinfo,89 stmt in varchar2)
  80. 90 return number
  81. 91 is
  82. 92
  83. 93 /* Variables */
  84. 94 -- Meta data.
  85. 95 r_Meta pkg_pipeline.anytype_Metadata_rec;
  86. 96
  87. 97 begin
  88. 98
  89. 99 r_Meta.typecode := tf_info.rettype.getattreleminfo(
  90. 100 1,r_Meta.precision,r_Meta.scale,r_Meta.length,101 r_Meta.csid,r_Meta.csfrm,r_Meta.type,r_Meta.name
  91. 102 );
  92. 103
  93. 104 sctx := dyn_pipeline(r_Meta.type);
  94. 105 return odciconst.success;
  95. 106
  96. 107 end;
  97. 108
  98. 109
  99. 110 /*
  100. 111 * START step. this is where we execute the cursor prior to fetching from it.
  101. 112 */
  102. 113 static function ODCITablestart(sctx in out dyn_pipeline,114 stmt in varchar2)
  103. 115 return number
  104. 116 is
  105. 117
  106. 118 /* Variables */
  107. 119 r_Meta pkg_pipeline.anytype_Metadata_rec;
  108. 120 v_sql varchar2(32767);
  109. 121 begin
  110. 122
  111. 123 v_sql := replace(stmt,null);
  112. 124 pkg_pipeline.r_sql.cursor := dbms_sql.open_cursor;
  113. 125 dbms_sql.parse(pkg_pipeline.r_sql.cursor,dbms_sql.native);
  114. 126 dbms_sql.describe_columns2(pkg_pipeline.r_sql.cursor,127 pkg_pipeline.r_sql.column_cnt,128 pkg_pipeline.r_sql.description);
  115. 129
  116. 130 -- define all the columns found to let Oracle know the datatypes.
  117. 131 for i in 1..pkg_pipeline.r_sql.column_cnt
  118. 132 loop
  119. 133
  120. 134 r_Meta.typecode := sctx.atype.GetAttrElemInfo(
  121. 135 i,136 r_Meta.csid,r_Meta.name
  122. 137 );
  123. 138
  124. 139 case r_Meta.typecode
  125. 140 when dbms_types.typecode_varchar2
  126. 141 then
  127. 142 dbms_sql.define_column(pkg_pipeline.r_sql.cursor,i,'',32767);
  128. 143 when dbms_types.typecode_number
  129. 144 then
  130. 145 dbms_sql.define_column(pkg_pipeline.r_sql.cursor,cast(null as number));
  131. 146 when dbms_types.typecode_date
  132. 147 then
  133. 148 dbms_sql.define_column(pkg_pipeline.r_sql.cursor,cast(null as date));
  134. 149 when dbms_types.typecode_raw
  135. 150 then
  136. 151 dbms_sql.define_column_raw(pkg_pipeline.r_sql.cursor,cast(null as raw),r_Meta.length);
  137. 152 when dbms_types.typecode_timestamp
  138. 153 then
  139. 154 dbms_sql.define_column(pkg_pipeline.r_sql.cursor,cast(null as timestamp));
  140. 155 when dbms_types.typecode_timestamp_tz
  141. 156 then
  142. 157 dbms_sql.define_column(pkg_pipeline.r_sql.cursor,cast(null as timestamp with time zone));
  143. 158 when dbms_types.typecode_timestamp_ltz
  144. 159 then
  145. 160 dbms_sql.define_column(pkg_pipeline.r_sql.cursor,cast(null as timestamp with local time zone));
  146. 161 when dbms_types.typecode_interval_ym
  147. 162 then
  148. 163 dbms_sql.define_column(pkg_pipeline.r_sql.cursor,cast(null as interval year to month));
  149. 164 when dbms_types.typecode_interval_ds
  150. 165 then
  151. 166 dbms_sql.define_column(pkg_pipeline.r_sql.cursor,cast(null as interval day to second));
  152. 167 when dbms_types.typecode_clob
  153. 168 then
  154. 169 case pkg_pipeline.r_sql.description(i).col_type
  155. 170 when 8
  156. 171 then
  157. 172 dbms_sql.define_column_long(pkg_pipeline.r_sql.cursor,i);
  158. 173 else
  159. 174 dbms_sql.define_column(pkg_pipeline.r_sql.cursor,cast(null as clob));
  160. 175 end case;
  161. 176 end case;
  162. 177 end loop;
  163. 178
  164. 179 -- execute the sql.
  165. 180 pkg_pipeline.r_sql.execute := dbms_sql.execute(pkg_pipeline.r_sql.cursor);
  166. 181
  167. 182 return odciconst.success;
  168. 183
  169. 184 end ODCITablestart;
  170. 185
  171. 186
  172. 187 /*
  173. 188 * FETCH step.
  174. 189 */
  175. 190 member function ODCITablefetch(self in out dyn_pipeline,191 nrows in number,192 rws out anydataset)
  176. 193 return number
  177. 194 is
  178. 195
  179. 196 /* Variables */
  180. 197 -- Buffers to hold values.
  181. 198 v_vc_col varchar2(32767);
  182. 199 v_num_col number;
  183. 200 v_date_col date;
  184. 201 v_raw_col raw(32767);
  185. 202 v_raw_error number;
  186. 203 v_raw_len integer;
  187. 204 v_int_ds_col interval day to second;
  188. 205 v_int_ym_col interval year to month;
  189. 206 v_ts_col timestamp;
  190. 207 v_tstz_col timestamp with time zone;
  191. 208 v_tsltz_col timestamp with local time zone;
  192. 209 v_clob_col clob;
  193. 210 v_clob_offset integer := 0;
  194. 211 v_clob_len integer;
  195. 212 -- Metadata
  196. 213 r_Meta pkg_pipeline.anytype_Metadata_rec;
  197. 214
  198. 215 begin
  199. 216
  200. 217 if dbms_sql.fetch_rows( pkg_pipeline.r_sql.cursor ) > 0
  201. 218 then
  202. 219
  203. 220 -- Describe to get number and types of columns.
  204. 221 r_Meta.typecode := self.atype.getinfo(
  205. 222 r_Meta.precision,223 r_Meta.csid,r_Meta.schema,224 r_Meta.name,r_Meta.version,r_Meta.attr_cnt
  206. 225 );
  207. 226
  208. 227 anydataset.begincreate(dbms_types.typecode_object,self.atype,rws);
  209. 228 rws.addinstance();
  210. 229 rws.piecewise();
  211. 230
  212. 231 -- loop through each column extracting value.
  213. 232 for i in 1..pkg_pipeline.r_sql.column_cnt
  214. 233 loop
  215. 234
  216. 235 r_Meta.typecode := self.atype.getattreleminfo(
  217. 236 i,237 r_Meta.csid,r_Meta.attr_type,238 r_Meta.attr_name
  218. 239 );
  219. 240
  220. 241 case r_Meta.typecode
  221. 242 when dbms_types.typecode_varchar2
  222. 243 then
  223. 244 dbms_sql.column_value(pkg_pipeline.r_sql.cursor,v_vc_col);
  224. 245 rws.setvarchar2(v_vc_col);
  225. 246 when dbms_types.typecode_number
  226. 247 then
  227. 248 dbms_sql.column_value(pkg_pipeline.r_sql.cursor,v_num_col);
  228. 249 rws.setnumber(v_num_col);
  229. 250 when dbms_types.typecode_date
  230. 251 then
  231. 252 dbms_sql.column_value(pkg_pipeline.r_sql.cursor,v_date_col);
  232. 253 rws.setdate(v_date_col);
  233. 254 when dbms_types.typecode_raw
  234. 255 then
  235. 256 dbms_sql.column_value_raw(pkg_pipeline.r_sql.cursor,v_raw_col,257 v_raw_error,v_raw_len);
  236. 258 rws.setraw(v_raw_col);
  237. 259 when dbms_types.typecode_interval_ds
  238. 260 then
  239. 261 dbms_sql.column_value(pkg_pipeline.r_sql.cursor,v_int_ds_col);
  240. 262 rws.setintervalds(v_int_ds_col);
  241. 263 when dbms_types.typecode_interval_ym
  242. 264 then
  243. 265 dbms_sql.column_value(pkg_pipeline.r_sql.cursor,v_int_ym_col);
  244. 266 rws.setintervalym(v_int_ym_col);
  245. 267 when dbms_types.typecode_timestamp
  246. 268 then
  247. 269 dbms_sql.column_value(pkg_pipeline.r_sql.cursor,v_ts_col);
  248. 270 rws.settimestamp(v_ts_col);
  249. 271 when dbms_types.typecode_timestamp_tz
  250. 272 then
  251. 273 dbms_sql.column_value(pkg_pipeline.r_sql.cursor,v_tstz_col);
  252. 274 rws.settimestamptz(v_tstz_col);
  253. 275 when dbms_types.typecode_timestamp_ltz
  254. 276 then
  255. 277 dbms_sql.column_value(pkg_pipeline.r_sql.cursor,v_tsltz_col);
  256. 278 rws.settimestampltz(v_tsltz_col);
  257. 279 when dbms_types.typecode_clob
  258. 280 then
  259. 281 case pkg_pipeline.r_sql.description(i).col_type
  260. 282 when 8
  261. 283 then
  262. 284 loop
  263. 285 dbms_sql.column_value_long(pkg_pipeline.r_sql.cursor,32767,v_clob_offset,286 v_vc_col,v_clob_len);
  264. 287 v_clob_col := v_clob_col || v_vc_col;
  265. 288 v_clob_offset := v_clob_offset + 32767;
  266. 289 exit when v_clob_len < 32767;
  267. 290 end loop;
  268. 291 else
  269. 292 dbms_sql.column_value(pkg_pipeline.r_sql.cursor,v_clob_col);
  270. 293 end case;
  271. 294 rws.setclob(v_clob_col);
  272. 295 end case;
  273. 296 end loop;
  274. 297
  275. 298 rws.endcreate();
  276. 299
  277. 300 end if;
  278. 301
  279. 302 return ODCIConst.Success;
  280. 303
  281. 304 end;
  282. 305
  283. 306 /*
  284. 307 * CLOSE step. close the cursor.
  285. 308 */
  286. 309 member function ODCITableClose(self in dyn_pipeline)
  287. 310 return number
  288. 311 is
  289. 312
  290. 313
  291. 314 begin
  292. 315 dbms_sql.close_cursor( pkg_pipeline.r_sql.cursor );
  293. 316 pkg_pipeline.r_sql := null;
  294. 317 return odciconst.success;
  295. 318 end ODCITableClose;
  296. 319
  297. 320 end;
  298. 321 /
  299.  
  300. Type body created.

完成后,您可以查询如下:

  1. sql> select * from table(pkg_pipeline.querydb('select * from dual'));
  2.  
  3. D
  4. -
  5. X
  6.  
  7. sql> select * from table(pkg_pipeline.querydb('select * from v$mystat where rownum <= 2'));
  8.  
  9. SID STATISTIC# VALUE
  10. ---------- ---------- ----------
  11. 230 0 1
  12. 230 1 1

猜你在找的Oracle相关文章