Курсор Oracle pl/sql - объединение записей или эквивалент

У меня есть класс PHP A и класс B. Они существуют независимо, и для каждого из них у меня есть эквивалентные определения Oracle PL/SQL, т.е.

type cursorA is ref cursor return recordA;
type cursorB is ref cursor return recordB;

позволяя возвращать несколько строк данных для создания нескольких объектов A или B PHP в одном вызове базы данных. Все идет нормально...

В определенных обстоятельствах мне требуется, чтобы один запрос возвращал объединенные поля записи A и записи B в одном курсоре A + B.

Я могу добиться этого, создав новую единственную запись C, объединяющую все поля из записей A и записей B, а затем выполнив курсор C, чтобы вернуть логическую информацию «A + B», однако это эффективно дублирует определения записей A и B, и я бы предпочел избежать этого с помощью делать что-то вроде:

type recordC is record (recordA plus recordB);
type cursorC is refcursor return recordC;

or

type cursorC is ref cursor return recordA plus recordB;

Приведенные выше утверждения не работают, но меня интересует, возможно ли в PL/SQL достичь некоторого эквивалента, который позволит повторно использовать/объединять определения записи A и записи B, а не требовать дублирования полей записи A и записи B в записьC.

Чтобы было ясно, это НЕ дубликат «объединения данных из курсоров в один». Это одиночный запрос, создающий 1 курсор, возвращаемые столбцы которого имеют значение recordC. «Разделение» запроса на 2 отдельных запроса может привести к значительному снижению производительности, и это не та функциональность, которую я ищу.


person Pancho    schedule 24.07.2015    source источник
comment
Я считаю, что это зависит от того, как вы сопоставляете поля pl/sql со свойствами класса php.   -  person Sebas    schedule 24.07.2015
comment
Привет @sebas - спасибо, компонент PHP, возможно, немного вводит в заблуждение, поскольку этот вопрос касается Oracle; в частности, способность Oracle объединять более 1 определения записи в одно определение суперзаписи, позволяющее повторно использовать определение записи. (обратите внимание, что это не то же самое, что вложенные записи Oracle, поскольку я не хочу, чтобы родительские дочерние отношения были для полей, просто плоский список объединенных полей)... Я должен сказать, что из того, что я прочитал, это не так. кажется невозможным, но я надеюсь, что у кого-то может быть понимание того, что мне не хватает.   -  person Pancho    schedule 25.07.2015
comment
Почему бы не создать один тип записи, содержащий все типы полей из обеих таблиц, и не использовать его в третьем курсоре, определенном как явный выбор со всеми нужными вам полями? Вы хотите сделать это динамически, автоматически добавляя результаты обоих курсоров?   -  person Sebas    schedule 25.07.2015
comment
@sebas - спасибо за предложение. Это возможность, но я также боюсь, что я не совсем неравнодушен, поскольку она не обеспечивает инкапсуляцию, которую я хотел бы на уровне A и B. Просто для фона, моя причина слияния с C - производительность и простота. т.е. поэтому данные могут быть возвращены в одном SQL-запросе и одном курсоре из БД, а затем разделены на различные клиентские классы PHP в веб-среде. Этот подход может даже повлечь за собой доставку данных для более чем 2 классов (все имеют отношение 1:1) за один вызов.   -  person Pancho    schedule 25.07.2015
comment
Тогда вы можете использовать динамический курсор, построенный на лету с определениями разыскиваемых объектов (которые должны где-то храниться). Звучит как интересный проект :) Но, свято, как-то запутанно :P   -  person Sebas    schedule 25.07.2015
comment
Вероятно, связано: stackoverflow.com/questions/4085014 /   -  person Typo    schedule 26.07.2015


Ответы (1)


Нет. PL/SQL не поддерживает манипулирование типами (записи или курсора) во время выполнения/компиляции (reflection), но типы данных очень статичны (и базовые). В некоторых областях PL/SQL является несколько старомодным и многословным языком.

Самый PL/SQlish способ объединения записей:

type recordC is record(
  a recordA
 ,b recordB
);

Но основная сила PL/SQL заключается в части SQL, поэтому, если вы можете настроить свои операторы select, вы можете рассмотреть следующий вариант, в котором данные как A, так и B (foo и bar соответственно) объединяются. Это, конечно, предполагает, что между ними существует разумная связь (в этом примере foo.id = bar.id):

create table foo (id number, str varchar2(10));
create table bar (id number, num number);

insert all
into foo(id, str) values(1, 'foo one')
into foo(id, str) values(2, 'foo two')
into bar(id, num) values(1, 100)
into bar(id, num) values(2, 200)
select 1 from dual;

select foo.id, foo.str as foo_str, bar.num as bar_num
from foo
inner join bar on bar.id = foo.id
;

Это ваш выбор, если вам нравится этот компромисс.

Другие возможные варианты, собранные из комментария Typo:

person user272735    schedule 27.07.2015
comment
Спасибо. Можете ли вы заставить курсор работать, возвращая вашу запись C выше, как я не мог. Тип кода cursorC — это refcursor return recordC; компилируется, но не выполняется при выполнении. Если вы можете запустить его, вставьте сюда пример кода! Благодарность! - person Pancho; 29.07.2015