我有一个返回记录数据类型的函数(2个字段:ID和Name)。如何从select语句中获取数据?
具体来说,我正在尝试使用OracleCommand对象尝试将对象放入我的C#代码中。我最初试过......
CALL FUNCTION_NAME() INTO :loRetVal
...但是对于我使用的任何类型,我都会收到数据类型错误。我也试过......
SELECT * FROM FUNCTION_NAME()
......和......
SELECT * FROM TABLE ( FUNCTION_NAME() )
......无济于事。我想我正在寻找......
SELECT * FROM RECORD ( FUNCTION_NAME() )
......当然,这不存在。
我能够提出的唯一解决方案是在另一个函数调用中包装此函数调用,其中外部函数返回包含此唯一记录的记录表。然而,这似乎很麻烦,我正在寻找一种更简单的方法。任何帮助将不胜感激。
编辑:对不起,我也尝试了SELECT FUNCTION_NAME() FROM DUAL
。
答案 0 :(得分:6)
记录数据类型是PL / SQL数据类型。 SQL不知道它。这可能是你收到错误的原因。见这个例子:
SQL> create package mypkg
2 as
3 type myrec is record
4 ( id int
5 , name varchar2(10)
6 );
7 function f return myrec;
8 end mypkg;
9 /
Package created.
SQL> create package body mypkg
2 as
3 function f return myrec
4 is
5 r myrec;
6 begin
7 r.id := 1;
8 r.name := 'test';
9 return r;
10 end f;
11 end mypkg;
12 /
Package body created.
SQL> desc mypkg
FUNCTION F RETURNS RECORD
ID NUMBER(38) OUT
NAME VARCHAR2(10) OUT
SQL> select mypkg.f from dual
2 /
select mypkg.f from dual
*
ERROR at line 1:
ORA-00902: invalid datatype
我指的是SQL中的错误。 您可以通过PL / SQL调用它:
SQL> declare
2 r mypkg.myrec;
3 begin
4 r := mypkg.f;
5 dbms_output.put_line(r.id);
6 dbms_output.put_line(r.name);
7 end;
8 /
1
test
PL/SQL procedure successfully completed.
如果要在SQL中使用该函数,则可以创建SQL对象类型。请注意,直接从C#调用函数看起来比坚持使用SQL执行此操作更为可取。但仅仅是为了记录:
SQL> drop package mypkg
2 /
Package dropped.
SQL> create type myobj is object
2 ( id int
3 , name varchar2(10)
4 );
5 /
Type created.
SQL> create package mypkg
2 as
3 function f return myobj;
4 end mypkg;
5 /
Package created.
SQL> create package body mypkg
2 as
3 function f return myobj
4 is
5 begin
6 return myobj(1,'test');
7 end f;
8 end mypkg;
9 /
Package body created.
SQL> select mypkg.f from dual
2 /
F(ID, NAME)
--------------------------------------------------------------
MYOBJ(1, 'test')
1 row selected.
此致 罗布。
答案 1 :(得分:2)
我认为这就是你要找的东西;在select语句中获取值:
select result.id as id, result.name
from ( select function() as result from dual);
因为您的函数返回的记录不是本机类型,所以您无法使用标准方法。如果您想将实际记录作为对象获取到C#中,那么您可以在ODP .net文档中对用户定义的类型进行一些阅读。
您还可以将该函数包装在另一个返回引用游标的函数中,并以更标准的方式在C#中使用。
答案 2 :(得分:2)
你能
吗?CREATE TYPE <object name> AS TABLE OF <record type>
并直接在SQL语句中使用它?我问,因为我有一个无法编辑的存储过程。存储过程有一个输出变量,它是我必须在SQL语句中引用的记录类型。我已经创建了一个调用proc的函数,但是如果我不必将记录转换为类型对象就好了。
我后来称之为:
SELECT *
FROM TABLE( CAST( <function name>() as <object name>));
答案 3 :(得分:1)
我对Rob van Wijk的评论格式很糟糕。继续他的想法。
-- create a collection type
CREATE TYPE myobj_tab AS TABLE OF myobj;
-- have the function return a collection type
CREATE OR REPLACE function f return myobj_tab
IS
objtab myobj_tab;
BEGIN
objtab := myobj_tab(myobj(1,'test'));
return objtab;
end f;
-- CAST it as a table and straight up select from it.
SELECT id, name FROM TABLE(CAST(f() AS myobj_tab));
答案 4 :(得分:1)
我认为您正在寻找PIPELINED功能:
CREATE TABLE test_table(tt_id INTEGER,tt_text VARCHAR2(40));
CREATE PACKAGE test_pkg IS
TYPE tp_rec IS RECORD(tt_id INTEGER,tt_text VARCHAR2(40));
TYPE tp_recs IS TABLE OF tp_rec;
FUNCTION test_func RETURN tp_recs PIPELINED;
FUNCTION test_func1 RETURN tp_recs PIPELINED;
FUNCTION test_func2(ivar INTEGER) RETURN tp_recs PIPELINED;
END;
/
CREATE OR REPLACE PACKAGE BODY test_pkg IS
FUNCTION test_func RETURN tp_recs PIPELINED
AS
currec tp_rec;
BEGIN
currec.tt_id := 1;
currec.tt_text := 'test1';
PIPE ROW(currec);
END;
FUNCTION test_func1 RETURN tp_recs PIPELINED
AS
currec tp_rec;
CURSOR t_cursor IS
SELECT * FROM test_table;
BEGIN
OPEN t_cursor;
LOOP
FETCH t_cursor INTO currec;
EXIT WHEN t_cursor%NOTFOUND;
PIPE ROW(currec);
END LOOP;
CLOSE t_cursor;
END;
FUNCTION test_func2(ivar INTEGER) RETURN tp_recs PIPELINED
AS
currec tp_rec;
BEGIN
SELECT * INTO currec FROM test_table WHERE tt_id = ivar;
PIPE ROW(currec);
END;
END;
/
BEGIN
INSERT INTO test_table VALUES(1,'test1');
INSERT INTO test_table VALUES(2,'test2');
INSERT INTO test_table VALUES(3,'test3');
COMMIT;
END;
/
SELECT * FROM TABLE(test_pkg.test_func());
SELECT * FROM TABLE(test_pkg.test_func1());
SELECT * FROM TABLE(test_pkg.test_func2(2));
上面的代码已经过测试,应该会给你一个良好的开端。只需在Oracle中查找PIPELINED关键字以获取更多信息(假设您正在使用Oracle ...)
答案 5 :(得分:0)
为什么你需要使用SQL?您可以只使用System.Data.CommandType.StoredProcedure来调用该函数。