Oracle Добавить новую функцию-член/процедуру к типу объекта

Я пытаюсь сделать следующее; скажем, я создал тип объекта в Oracle

create type test as object(
name varchar2(12),
member procedure print1);
/
create type body test is
member procedure print1 is
begin
dbms_output.put_line('Test');
end print1;
end;
/

Теперь я хочу добавить новую процедуру-член print2 — опять же, я могу сделать это, набрав:

alter type test
add member procedure print2 cascade;

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

Я просмотрел документацию и Интернет, но не смог найти ответ, и мне кажется глупым, что Oracle ожидает, что разработчик снова введет все определения.

С уважением, Джордж


person user998388    schedule 11.12.2011    source источник
comment
Можете ли вы получить тело текущего типа из user_source?   -  person Jon Heller    schedule 11.12.2011
comment
Конечно, но какая разница?   -  person user998388    schedule 11.12.2011
comment
Если у вас есть исходный код, нужно ли вам знать, как они реализовали код? Разве вы не можете просто скопировать и вставить все это и добавить новую процедуру в конец?   -  person Jon Heller    schedule 11.12.2011
comment
Возможно, если вы потратите пару дней. Таблица довольно длинная и включает в себя множество курсоров и других определяемых пользователем объектов. Есть ли способ избежать этого и просто сказать, что вот новая спецификация, объединив ее с предыдущими?   -  person user998388    schedule 11.12.2011


Ответы (2)


Как насчет создания процедуры, которая динамически добавляет определение к типу:

create or replace procedure add_procedure(p_new_procedure_definition varchar2)
    authid current_user
is
    v_object_type_body varchar2(32767) := 'create or replace ';
begin
    --Build string with current definitions
    for source_code in
    (
        select text
        from user_source
        where name = 'TEST'
            and type = 'TYPE BODY'
        order by line
    ) loop
        --Don't include the last "END;" yet.
        --(Huge assumption that the package ends with "END;")
        if replace(upper(trim(source_code.text)),chr(10)) <> 'END;' then
            v_object_type_body := v_object_type_body||source_code.text;
        end if;
    end loop;

    --Add new definition    
    v_object_type_body := v_object_type_body||chr(10)||
        p_new_procedure_definition||chr(10)||'end;';

    --For debugging
    --dbms_output.put_line(v_object_type_body);

    --Compile the type
    execute immediate v_object_type_body;
end;
/

Затем запустите его следующим образом:

begin
    add_procedure(
    '
    member procedure print2 is
    begin
        dbms_output.put_line(''Test2'');
    end print2;
    '
    );
end;
/

Хотя вам нужно сделать некоторые довольно большие предположения о том, как закончится пакет. Чтобы сделать это действительно универсальное решение, вам нужно создать анализатор PL/SQL, что в принципе невозможно. И процедура будет работать только с 32 КБ, если типы очень большие, вам, вероятно, придется использовать CLOB.

person Jon Heller    schedule 12.12.2011
comment
Это действительно здорово! Но как мне теперь изменить (и отказаться) процедуру? ...И как мне быть с разными подписями? :) - person HAL 9000; 12.12.2011
comment
Я не думаю, что есть хороший способ сделать это. Есть опция DROP, но, как и в случае с ADD, она применяется только к спецификации. Я думаю, что настоящее решение этой проблемы — не делать этого. - person Jon Heller; 13.12.2011

Используйте Oracle SQL Developer, чтобы изменить тело типа.

Или используйте любой текстовый редактор, чтобы изменить исходный файл и запустить его в вашей любимой командной строке SQL.

Типы объектов — это самая передовая концепция программирования в Oracle. Может быть, вам было бы лучше с автономными функциями?

Тем не менее, я понимаю вашу точку зрения. Насколько я знаю, тело типа не может содержать функции, не указанные в спецификации. Порядок методов также не должен иметь значения, поэтому, похоже, нет причин не использовать эту опцию.

person HAL 9000    schedule 11.12.2011
comment
У меня нет исходного кода. Кроме того, не было бы смысла, если бы существовала команда процедуры добавления члена тела типа alter type? Я знаю, что для типа body не разрешено ничего, что не указано в спецификации, я просто спрашиваю, что вы можете добавить материал с помощью alter в спецификацию, можете ли вы сделать то же самое с телом? - person user998388; 12.12.2011
comment
Если у вас есть права на изменение спецификации типа, у вас есть доступ к исходному тексту. Вы просто не можете изменить его так же, как со спецификацией. Кажется, они (Oracle) забыли предоставить эту опцию. - person HAL 9000; 12.12.2011