2014-10-08 2 views
2

У меня есть следующий скрипт, который содержит функцию с именем 'myFunction'. (объявление типа rowValueTmp и rowValueTable также прилагается для информации). В принципе, мне нужно использовать имя таблицы в качестве входного параметра для myFunction. Я обнаружил, что мне нужно использовать динамический SQL, чтобы использовать имя таблицы в качестве параметра (пожалуйста, исправьте меня, если есть альтернативные способы сделать это). Итак, следующий код - это то, что я пробовал до сих пор.Oracle SQL Developer, используя динамический SQL в функции

create or replace type rowValueTmp as object (
    month number, 
    year number 
); 
/ 
create or replace type rowValueTable as table of rowValueTmp; 
/  
create or replace FUNCTION myFunction (TABLENAME in VARCHAR2) 
    return rowValueTable as 
     v_ret rowValueTable; 
    begin 
     execute immediate ' 
     select rowValueTmp(month, year) 
     bulk collect into v_ret 
     from '||TABLENAME;  
     return v_ret; 
    end myFunction; 
/
select * from table(myFunction('SCHEMA.TEST')); 

Но этот код дает мне ошибку, и я предположил, что эта ошибка произошла из-за использования «насыпной собирать» в выполнить непосредственный блок.

ORA-03001: unimplemented feature 

Если я заменяю содержание выполнить немедленное как следующий, выше скрипт работает ..

select rowValueTmp(month, year) 
bulk collect into v_ret 
from SCHEMA.TEST; 

Вопрос
1] Есть ли способ (а не динамический SQL), что я могу использовать имя таблицы в качестве входного параметра для myFunction?
2] Если мне не разрешено использовать Наличный сбор в выполнить немедленный блок, что вы предлагаете?

+0

'EXECUTE IMMEDIATE 'SELECT * FROM bulk_collect_test' BULK COLLECT INTO l_tab;', http://www.dba-oracle.com/plsql/t_plsql_dynamic.htm – Sebas

ответ

4

Вы можете возвращать значения из execute immediately в bulk collect:

CREATE OR REPLACE FUNCTION myfunction (tablename IN VARCHAR2) 
    RETURN rowvaluetable AS 
    v_ret rowvaluetable; 
    v_table VARCHAR2 (61) := DBMS_ASSERT.sql_object_name (tablename); 
BEGIN 
    EXECUTE IMMEDIATE ' 
     select rowValueTmp(month, year) 
     from ' || v_table 
     BULK COLLECT INTO v_ret; 

    RETURN v_ret; 
END myfunction; 
/

В интересах излишней осторожности, я бы рекомендовал использовать DBMS_ASSERT для проверки параметров таблицы, а также (как показано на рисунке).

+0

ничего себе ... это было так просто ..... ..... Спасибо!!!!!!! – Adrian

Смежные вопросы