2012-11-09 30 views
2

我的僱主使用一個應用程序,它將有關商業案例的元數據存儲在主表和大約40個明細表中。在包規範中聲明或定義遊標時,有沒有辦法避免定義記錄類型?

目前,我維護一個包,它從這些表中讀取併爲每個主記錄生成一個帶有HTML輸出的文件。

我的包體包含以下內容:

type output_text_type is table of varchar(32768); 
function fA(mri in master_record_identifier_type) 
     return output_text_type 
is 
cursor cA(if1 master_record_identifier_type.if1%type, ...) 
is 
select tA.f1, tA.f2, ... 
from tA 
where tA.if1 = if1 
...; 
begin -- fA 
     ... 
     for r in cA(mri.if1, mri.if2, ...) loop 
      <generate HTML using r.f1, r.rf2, mri.if1...> 
     end loop; 
end fA; 
... some 40 more function with the same structure ... 

BTW,最光標返回少於100個記錄(最常見的零個或一個),所以fetch ... bulk collect ...不會導致性能增益。

現在我們計劃與其他組織交換商業案例的元數據(當然還有文檔本身)。爲此,我們必須生成xml數據結構,其實質是相同的內容。爲了滿足這個要求,我打算在一個包pkg_cursors,一個pkg_html和一個(尚未被寫入)的pkg_xml包中分割我的當前包(受模型 - 視圖 - 控制器模式的思想的影響)。

唉,我只找到一個可行的解決方案通過定義一個記錄,如下所示:

create or replace package pkg_cursors 
as 
type rA is record(
     if1 tA.if1%type, 
     f1 tA.f1%type, 
     f2 tA.f2%type, 
     ... a dozen more fields ... 
     ); 
cursor ca(master_record_identifier_type.if1%type, ...) 
    return rA; 
... 

這是不幸的,對於到現在加上一欄表 導致光標的SELECT子句的更新和將新列添加到遊標爲循環。從現在起,我有第三個地方要考慮:記錄的定義。

我也嘗試在包規格光標:

create package pkg_cursors 
as 
cursor cA(...) is 
select <select-list> 
from ... where ... 
return cA%rowtype; 

但我得到了編譯錯誤。

因此,我的問題是:有沒有辦法避免遊標返回參數的記錄定義?

您是否認爲有更好的方法來拆分包?

(請原諒我的語言錯誤和這個問題的長度。請問我的英語水平更加堅實,這個問題將可能會更短。)

+0

你有沒有考慮過動態html? dbms_sql可以執行此操作(請參閱dbms_sql.describe_columns) – DazzaL

回答

1

動態SQL樣品如果任何幫助你的問題?當然不必是流水線,我只是這樣做了。

SQL> create table one (id number, foo varchar2(20), if1 number); 

Table created. 

SQL> create table two (id number, foo varchar2(20), foo2 date, if1 number); 

Table created. 

SQL> insert into one values(1, 'test', 1); 

1 row created. 

SQL> insert into one values(1, 'test again', 1); 

1 row created. 

SQL> insert into two values(1, '2nd table', sysdate-1, 1); 

1 row created. 

SQL> insert into two values(1, '2nd table - 2', sysdate-10, 1); 

1 row created. 

SQL> insert into two values(1, '2nd table - 3', sysdate-3, 1); 

1 row created. 

SQL> create type vc_tab as table of varchar2(4000); 
    2/

Type created. 

SQL> create or replace function gen_html(p_tab in varchar2, p_master_id in number) 
    2 return vc_tab 
    3 pipelined 
    4 is 
    5 v_cur   integer default dbms_sql.open_cursor; 
    6 v_col_val  varchar2(4000); 
    7 v_col_val_clob clob; 
    8 v_status  integer; 
    9 v_desc_tbl  dbms_sql.desc_tab; 
10 v_col_cnt  number; 
11 v_row   varchar2(4000); 
12 begin 
13 execute immediate 'alter session set nls_date_format=''dd-mon-yyyy hh24:mi:ss'' '; 
14 execute immediate 'alter session set nls_timestamp_tz_format=''dd-mon-yyyy hh24:mi:ssxff tzh:tzm'''; 
15 execute immediate 'alter session set nls_timestamp_format=''dd-mon-yyyy hh24:mi:ssxff'''; 
16 
17 dbms_sql.parse(v_cur, 'select * from ' || dbms_assert.simple_sql_name(p_tab) || ' where if1 = :b1', 
18     dbms_sql.native); 
19 dbms_sql.bind_variable(v_cur, 'b1', p_master_id); 
20 dbms_sql.describe_columns(v_cur, v_col_cnt, v_desc_tbl); 
21 
22 for i in 1 .. v_col_cnt 
23 loop 
24  if (v_desc_tbl(i).col_type = 109) 
25  then 
26  dbms_sql.define_column(v_cur, i, v_col_val_clob); 
27  else 
28  dbms_sql.define_column(v_cur, i, v_col_val, 4000); 
29  end if; 
30 end loop; 
31 
32 v_status := dbms_sql.execute(v_cur); 
33 
34 pipe row('<h1>' || p_tab || '</h1>'); 
35 pipe row('<table>'); 
36 while (dbms_sql.fetch_rows(v_cur) > 0) 
37 loop 
38  pipe row('<tr>'); 
39  for i in 1 .. v_col_cnt 
40  loop 
41  if (v_desc_tbl(i).col_type = 109) 
42  then 
43   dbms_sql.column_value(v_cur, i, v_col_val_clob); 
44   pipe row('<td>' || v_desc_tbl(i).col_name || '</td><td>' || v_col_val_clob || '</td>'); 
45  else 
46   dbms_sql.column_value(v_cur, i, v_col_val); 
47   pipe row('<td>' || v_desc_tbl(i).col_name || '</td><td>' || v_col_val || '</td>'); 
48  end if; 
49  end loop; 
50  pipe row('</tr>'); 
51 end loop; 
52 pipe row('</table>'); 
53 dbms_sql.close_cursor(v_cur); 
54 
55 end; 
56/

Function created. 

SQL> select * from table(gen_html('ONE', 1)); 

COLUMN_VALUE 
-------------------------------------------------------------------------------- 
<h1>ONE</h1> 
<table> 
<tr> 
<td>ID</td><td>1</td> 
<td>FOO</td><td>test</td> 
<td>IF1</td><td>1</td> 
</tr> 
<tr> 
<td>ID</td><td>1</td> 
<td>FOO</td><td>test again</td> 
<td>IF1</td><td>1</td> 
</tr> 
</table> 

13 rows selected. 

SQL> select * from table(gen_html('TWO', 1)); 

COLUMN_VALUE 
-------------------------------------------------------------------------------- 
<h1>TWO</h1> 
<table> 
<tr> 
<td>ID</td><td>1</td> 
<td>FOO</td><td>2nd table</td> 
<td>FOO2</td><td>08-nov-2012 18:37:36</td> 
<td>IF1</td><td>1</td> 
</tr> 
<tr> 
<td>ID</td><td>1</td> 
<td>FOO</td><td>2nd table - 2</td> 
<td>FOO2</td><td>30-oct-2012 18:37:36</td> 
<td>IF1</td><td>1</td> 
</tr> 
<tr> 
<td>ID</td><td>1</td> 
<td>FOO</td><td>2nd table - 3</td> 
<td>FOO2</td><td>06-nov-2012 18:37:36</td> 
<td>IF1</td><td>1</td> 
</tr> 
</table> 

21 rows selected. 
+0

感謝您提供詳細的答案。不幸的是,我的問題中的例子比真正的軟件包簡單得多。與其他記錄定義相比,您的解決方案會帶來更高的符號負擔。 –

相關問題