2015-04-02 1 views
0

Я изучал пакет DBMS_SQL в Oracle и пытался выяснить, есть ли способ создать представление или что-то, что пользователи могут выбрать, чтобы просмотреть результаты динамического SQL-запроса ,Разрешить пользователям SELECT из динамического SQL

У меня есть процедура тестирования на основе документации:

CREATE OR REPLACE PROCEDURE test_dyn_sql AS 
    cursor_name INTEGER; 
    rows_processed INTEGER; 
    l_query LONG; 
BEGIN 
    l_query := 'SELECT SYSDATE AS the_date, ''ABC'' AS the_string, 1 AS the_int FROM dual'; 
    cursor_name := dbms_sql.open_cursor; 
    DBMS_SQL.PARSE(cursor_name, l_query, DBMS_SQL.NATIVE); 
    rows_processed := DBMS_SQL.EXECUTE(cursor_name); 
    DBMS_SQL.CLOSE_CURSOR(cursor_name);  
EXCEPTION 
    WHEN OTHERS THEN 
    DBMS_SQL.CLOSE_CURSOR(cursor_name); 
    DBMS_OUTPUT.put_line('ERROR'); 
END; 

Но это просто выполняет оператор и не возвращает ничего. То, что мне нужно, - это представление, так что пользователь может просто сделать SELECT the_date FROM some_view и получить результаты. Я не буду знать имена или количество столбцов заранее, поэтому я после динамического SQL-решения.

+0

Я не думаю, что есть какой-либо способ сделать это. На самом деле это не тот взгляд. Вы могли бы создать функцию, которая каким-то образом возвращает таблицу? См. [This] (http://oracle-base.com/articles/misc/pipelined-table-functions.php) пример функции таблицы. – OldProgrammer

ответ

1

«Я не буду знать имена или количество столбцов заранее, так что это , почему я после динамического SQL-решения«

Это довольно сложно реализовать в SQL: SQL - это все о структурах данных, и он действительно ожидает, что столбцы будут существовать спереди. Таким образом, вы не можете создать VIEW в изменяемой структуре данных.

Вы можете реализовать функцию, которая возвращает курсор. Это указатель на структуру данных, которая может быть интерпретирована клиентом, например JDBC ResultSet.

Вот пример функции, которая принимает имя таблицы и имя столбца, собирает запрос и возвращает его результирующий набор.

CREATE OR REPLACE FUNCTION test_dyn_sql 
    (tab_name in varchar2 
    , col_name in varchar2) 
    return sys_refcursor 
AS 
    return_value sys_refcursor; 
BEGIN 
    open return_value for 
    'SELECT SYSDATE AS the_date, '||col_name||' FROM '||tab_name; 
    return return_value; 
END; 
/

Выход не очень элегантный в SQL * Plus, но вы получаете эту идею.

SQL> select test_dyn_sql ('EMP', 'NAME') from dual; 

TEST_DYN_SQL('EMP',' 
-------------------- 
CURSOR STATEMENT : 1 

CURSOR STATEMENT : 1 

THE_DATE NAME 
--------- ------------------------------ 
03-APR-15 FOX IN SOCKS 
03-APR-15 MR KNOX 
03-APR-15 DAISY-HEAD MAYZIE 


SQL> 

Я предлагаю вам придерживаться Native Dynamic SQL (то есть, execute immediate) как можно больше: как вы можете видеть, это очень простой по сравнению с DBMS_SQL. Используйте только DBMS_SQL, когда у вас есть чрезвычайно сложное требование.

Я благодарен, что это не может быть форма решения, которое вы ищете. Если это так, то отредактируйте ваш вопрос, чтобы предоставить более подробную информацию о проблеме, которую вы пытаетесь решить.

0

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

CREATE OR REPLACE FUNCTION test_dyn_sql(asd INTEGER) RETURN INTEGER AS 
     cursor_name INTEGER; 
     rows_processed INTEGER; 
     l_query LONG; 
    BEGIN 
     l_query := 'SELECT SYSDATE AS the_date, ''ABC'' AS the_string, 1 AS the_int FROM dual'; 
     cursor_name := dbms_sql.open_cursor; 
     DBMS_SQL.PARSE(cursor_name, l_query, DBMS_SQL.NATIVE); 
     rows_processed := DBMS_SQL.EXECUTE(cursor_name); 
     DBMS_SQL.CLOSE_CURSOR(cursor_name);  
     RETURN rows_processed; 
    EXCEPTION 
     WHEN OTHERS THEN 
     DBMS_SQL.CLOSE_CURSOR(cursor_name); 
     DBMS_OUTPUT.put_line('ERROR'); 
     RETURN 0; 
    END; 

Это, как вы вызываете функцию от PLSQL

DECLARE 
    rows_precessed INTEGER; 
BEGIN 
    rows_precessed := test_dyn_sqll(0); 
    DBMS_OUTPUT.put_line(rows_precessed); 
END;