Oracle: выберите из типа записанных данных - PullRequest
4 голосов
/ 20 июня 2009

У меня есть функция, которая возвращает тип данных записи (2 поля: ID и Имя). Как я могу получить данные из оператора 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.

Ответы [ 6 ]

6 голосов
/ 20 июня 2009

Тип записи - это тип данных 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.

С уважением, Роб.

2 голосов
/ 30 июня 2009

Можете ли вы

CREATE TYPE <object name> AS TABLE OF <record type> 

и использовать это непосредственно в операторе SQL? Я спрашиваю, потому что у меня есть сохраненный процесс, который я не могу редактировать. Хранимая процедура имеет выходную переменную типа записи, на которую я должен ссылаться в операторе SQL. Я уже создал функцию для вызова процедуры, но если мне не нужно преобразовывать запись в тип объекта, это было бы неплохо.

Позже я бы назвал это так:

SELECT *
FROM TABLE( CAST( <function name>() as <object name>));
2 голосов
/ 20 июня 2009

Я думаю, это то, что вы ищете; чтобы получить значения в операторе выбора:

select result.id as id, result.name
  from ( select function() as result from dual);

Поскольку ваша функция возвращает запись не собственного типа, вы не можете использовать стандартные методы. Если вы хотите получить фактическую запись в виде объекта в C #, вам нужно прочитать определенные пользователем типы в документации ODP .net.

Вы также можете заключить функцию в другую функцию, которая возвращает курсор ref и которая используется в C # более стандартным способом.

1 голос
/ 12 октября 2009

Я думаю, что вы ищете 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));

Приведенный выше код протестирован и должен дать вам хорошее начало. Просто найдите ключевое слово PIPELINED в Oracle для получения дополнительной информации (при условии, что вы работаете с Oracle ...)

1 голос
/ 20 июня 2009

Форматирование моего комментария для Роба ван Вейк плохое. Чтобы продолжить свою мысль.

-- 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));
0 голосов
/ 20 июня 2009

Зачем вам вообще нужен SQL? Вы можете просто использовать System.Data.CommandType.StoredProcedure для вызова функции.

колл-ан-оракул-функция-из-C #

Вызов функции Oracle в пакете с C #

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...