我知道这是可能的:
SQL> create or replace type tp_asset as object (assetId number, asset_name varchar2(100), asset_val number)
2 /
Type created
SQL> create or replace type tp_tab_asset is table of tp_asset;
2 /
Type created
SQL> create or replace function fnc_AssetAttributeByType(p_num in number) return tp_tab_asset pipelined as
2 v_tp_asset tp_asset;
3 begin
4 for i in 1 .. 3
5 loop
6 v_tp_asset := tp_asset(i, 'ABC', i * 3);
7 pipe row (v_tp_asset);
8 end loop;
9 return;
10 end;
11 /
Function created
但这看起来非常愚蠢。为什么我要在两个位置维护列的列表?我正在将T-SQL翻译成Oracle,我想做以下事情:
create or replace
FUNCTION fnc_AssetAttributeByType(
p_ATTRIBUTETYPEID IN NUMBER)
RETURN ******TABLE???????? pipelined
AS
BEGIN
FOR j IN
(
SELECT
a.AssetID,
ShortName,
LongName,
ATTRIBUTEVALUE
FROM
DBO$ASSET A
INNER JOIN dbo$asset_attribute aa
ON
A.ASSETID = AA.ASSETID
INNER JOIN dbo$attribute att
ON
AA.ATTRIBUTEID = ATT.ATTRIBUTEID
WHERE
ATTRIBUTETYPEID = p_ATTRIBUTETYPEID
)
LOOP
pipe row (j);
END LOOP;
RETURN;
END;
告诉我,我是否理智,或者这不是Oracle超级说法的方式
答案 0 :(得分:0)
我可以考虑在包中声明一个类型,我可以通过使用视图的%rowtype列来实现它(从@Justin Cave借用)。
SQL> col shortname format a20
SQL> col longname format a20
SQL> drop table dbo$asset;
Table dropped
SQL> drop table dbo$asset_attribute;
Table dropped
SQL> drop table dbo$attribute;
Table dropped
SQL> create table dbo$asset (assetid number);
Table created
SQL> create table dbo$asset_attribute (attributeid number, assetid number, shortname varchar2(100), longname varchar2(100));
Table created
SQL> create table dbo$attribute (attributeid number, assetid number, attributevalue number, attributetypeid number);
Table created
SQL> insert into dbo$asset values (1);
1 row inserted
SQL> insert into dbo$asset_attribute values (10, 1, 'ATT1', 'ATTRIBUTE1');
1 row inserted
SQL> insert into dbo$asset_attribute values (20, 1, 'ATT2', 'ATTRIBUTE2');
1 row inserted
SQL> insert into dbo$attribute values (10, 1, 999.99, 444);
1 row inserted
SQL> insert into dbo$asset values (2);
1 row inserted
SQL> insert into dbo$asset_attribute values (30, 2, 'ATT1', 'ATTRIBUTE1');
1 row inserted
SQL> insert into dbo$asset_attribute values (40, 2, 'ATT2', 'ATTRIBUTE2');
1 row inserted
SQL> insert into dbo$attribute values (40, 2, 888.99, 555);
1 row inserted
SQL> create or replace view vw_assetattributebytype as
2 SELECT a.assetid, shortname, longname, attributevalue, attributetypeid
3 FROM dbo$asset a
4 JOIN dbo$asset_attribute aa ON a.assetid = aa.assetid
5 JOIN dbo$attribute att ON aa.attributeid = att.attributeid;
View created
SQL> create or replace package pck_asset is
2 type tp_assetattributebytype is table of vw_assetattributebytype%rowtype;
3
4 function fnc_assetattributebytype(p_attributetypeid in number) return tp_assetattributebytype pipelined;
5 end pck_asset;
6 /
Package created
SQL> create or replace package body pck_asset is
2
3 function fnc_assetattributebytype(p_attributetypeid in number) return tp_assetattributebytype pipelined is
4 begin
5 for j in (select *
6 from vw_assetattributebytype
7 where attributetypeid = p_attributetypeid)
8 loop
9 pipe row(j);
10 end loop;
11 end fnc_assetattributebytype;
12
13 end pck_asset;
14 /
Package body created
SQL> select *
2 from table(pck_asset.fnc_assetattributebytype(444));
ASSETID SHORTNAME LONGNAME ATTRIBUTEVALUE ATTRIBUTETYPEID
---------- -------------------- -------------------- -------------- ---------------
1 ATT1 ATTRIBUTE1 999,99 444
SQL>
问题是你需要在我的例子中将过滤器列ATTRIBUTETYPEID添加到视图中。有解决它的方法,即使使用应用程序上下文在视图内部进行过滤,它也相当简单。如果您必须仅使用查询中最初的列来保持视图,则可以执行此操作而不是:
SQL> col shortname format a20
SQL> col longname format a20
SQL> drop table dbo$asset;
Table dropped
SQL> drop table dbo$asset_attribute;
Table dropped
SQL> drop table dbo$attribute;
Table dropped
SQL> create table dbo$asset (assetid number);
Table created
SQL> create table dbo$asset_attribute (attributeid number, assetid number, shortname varchar2(100), longname varchar2(100));
Table created
SQL> create table dbo$attribute (attributeid number, assetid number, attributevalue number, attributetypeid number);
Table created
SQL> insert into dbo$asset values (1);
1 row inserted
SQL> insert into dbo$asset_attribute values (10, 1, 'ATT1', 'ATTRIBUTE1');
1 row inserted
SQL> insert into dbo$asset_attribute values (20, 1, 'ATT2', 'ATTRIBUTE2');
1 row inserted
SQL> insert into dbo$attribute values (10, 1, 999.99, 444);
1 row inserted
SQL> insert into dbo$asset values (2);
1 row inserted
SQL> insert into dbo$asset_attribute values (30, 2, 'ATT1', 'ATTRIBUTE1');
1 row inserted
SQL> insert into dbo$asset_attribute values (40, 2, 'ATT2', 'ATTRIBUTE2');
1 row inserted
SQL> insert into dbo$attribute values (40, 2, 888.99, 555);
1 row inserted
SQL> create or replace context ctx_asset using pck_asset;
Context created
SQL> create or replace view vw_assetattributebytype as
2 SELECT a.assetid, shortname, longname, attributevalue
3 FROM dbo$asset a
4 JOIN dbo$asset_attribute aa ON a.assetid = aa.assetid
5 JOIN dbo$attribute att ON aa.attributeid = att.attributeid
6 WHERE attributetypeid = sys_context('ctx_asset', 'attributetypeid');
View created
SQL> create or replace package pck_asset is
2 type tp_assetattributebytype is table of vw_assetattributebytype%rowtype;
3
4 function fnc_assetattributebytype(p_attributetypeid in number) return tp_assetattributebytype pipelined;
5 procedure prc_set_attributetype(p_attributetypeid in number);
6
7 end pck_asset;
8 /
Package created
SQL> create or replace package body pck_asset is
2
3 procedure prc_set_attributetype(p_attributetypeid in number) is
4 begin
5 dbms_session.set_context('ctx_asset', 'attributetypeid', p_attributetypeid);
6 end;
7
8 function fnc_assetattributebytype(p_attributetypeid in number) return tp_assetattributebytype pipelined is
9 begin
10 -- sets the filter on the application context for the view
11 prc_set_attributetype(p_attributetypeid);
12
13 for j in (select *
14 from vw_assetattributebytype)
15 loop
16 pipe row(j);
17 end loop;
18 end fnc_assetattributebytype;
19
20 end pck_asset;
21 /
Package body created
SQL> select *
2 from table(pck_asset.fnc_assetattributebytype(555));
ASSETID SHORTNAME LONGNAME ATTRIBUTEVALUE
---------- -------------------- -------------------- --------------
2 ATT2 ATTRIBUTE2 888,99
SQL>
我对你的桌子结构做了很多假设,他们可能不正确,原谅我任何错误。想法是展示一个运行的示例代码。
答案 1 :(得分:0)
可以使用ANYDATASET和Oracle Data Cartridge创建一个返回未知列类型结果的Oracle函数。
我见过的唯一一个实现是Adrian Billington的Dictionary Long Application。该程序用于将LONG列转换为CLOB,以便更轻松地查询数据字典。通过删除LONG和CLOB代码,它将成为更通用的动态查询引擎。
虽然这是一个很棒的程序,但我通常建议不要使用它。有许多错误和限制。 ANY *类型很少使用且充满惊喜。
不幸的是,这主要是一个仅限链接的答案。解决这个看似简单的任务需要数百行拜占庭代码。这也是我建议您找到另一种方法的另一个原因,即使这意味着创建额外的TYPE。