Oracle:从记录数据类型中选择

Oracle:从记录数据类型中选择,oracle,Oracle,我有一个函数,它返回记录数据类型2字段:ID和Name。如何从select语句中获取数据 具体来说,我正在尝试使用OracleCommand对象,试图将该对象放入我的C代码中。我最初试过 CALL FUNCTION_NAME() INTO :loRetVal SELECT * FROM FUNCTION_NAME() 。。。但是无论我使用什么类型,我都会得到一个数据类型错误。我也试过 CALL FUNCTION_NAME() INTO :loRetVal SELECT * FROM FUN

我有一个函数,它返回记录数据类型2字段:ID和Name。如何从select语句中获取数据

具体来说,我正在尝试使用OracleCommand对象,试图将该对象放入我的C代码中。我最初试过

CALL FUNCTION_NAME() INTO :loRetVal
SELECT * FROM FUNCTION_NAME()
。。。但是无论我使用什么类型,我都会得到一个数据类型错误。我也试过

CALL FUNCTION_NAME() INTO :loRetVal
SELECT * FROM FUNCTION_NAME()
。。。而且

SELECT * FROM TABLE ( FUNCTION_NAME() )
。。。无济于事。我想我在找

SELECT * FROM RECORD ( FUNCTION_NAME() )
。。。当然,这是不存在的

我能想到的唯一解决方案是将这个函数调用包装到另一个函数调用中,在这个函数调用中,外部函数返回一个包含这个唯一记录的记录表。然而,这似乎很麻烦,我正在寻找一种更简单的方法。任何帮助都将不胜感激


编辑:很抱歉,我也尝试过从DUAL中选择函数名。

为什么需要使用SQL?您可能只需要使用System.Data.CommandType.StoredProcess调用该函数


我想这就是你想要的;要在select语句中获取值,请执行以下操作:

select result.id as id, result.name
  from ( select function() as result from dual);
因为函数返回的记录不是本机类型,所以不能使用标准方法。如果您想将实际记录作为对象输入C,那么您必须阅读ODP.net文档中的用户定义类型


您还可以将该函数包装到另一个函数中,该函数返回一个ref游标,并以更标准的方式在C中使用。

记录数据类型是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.
问候,,
Rob。

我对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));
你能吗

CREATE TYPE <object name> AS TABLE OF <record type> 
然后直接在SQL语句中使用它?我这样问是因为我有一个无法编辑的存储过程。存储的过程有一个输出变量,它是我必须在SQL语句中引用的记录类型。我已经创建了一个函数来调用proc,但是如果我不必将记录转换为type对象,那就太好了

我后来会这样称呼它:

SELECT *
FROM TABLE( CAST( <function name>() as <object name>));

我认为您正在寻找流水线功能:

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,只需在Oracle中查找PIPELINED关键字,了解更多信息…

我非常喜欢您的答案。继续走这条路。您可以创建一个集合并在SQL中强制转换它。-创建集合类型创建类型myobj_选项卡作为myobj的表;-让函数return a collection type创建或替换函数return myobj_tab为objtab myobj_tab;开始对象选项卡:=myobj_tabmyobj1,“测试”;返回objtab;完f;-将其转换为表格并直接从中选择。从TABLECASTf中选择id、名称作为myobj_选项卡;