允许用户从动态 SQL SELECT
Allow users to SELECT from dynamic SQL
我一直在查看 Oracle 中的 DBMS_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;
但这只是执行语句,并没有return任何东西。我想要的是一个视图,这样用户可以只执行 SELECT the_date FROM some_view
并获得结果。我不会事先知道名称或列数,所以这就是我寻求动态 SQL 解决方案的原因。
如果您希望代码 return rows_processed 变量的值,请使用下面的代码 return 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;
" I will not know the names or number of columns in advance, so that's
why I'm after a dynamic SQL solution"
这在 SQL 中很难实现:SQL 完全是关于数据结构的,它确实希望列预先存在。所以你不能在 mutable 数据结构上构建 VIEW。
您可以实现 returns 引用游标的功能。这是一个指向可以被客户端解释的数据结构的指针,比如 JDBC ResultSet。
这是一个示例函数,它采用 table 名称和列名称,组合查询和 returns 它的结果集。
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。
我知道这可能不是您正在寻找的解决方案。如果是这种情况,请编辑您的问题以提供有关您要解决的问题的更多详细信息。
我一直在查看 Oracle 中的 DBMS_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;
但这只是执行语句,并没有return任何东西。我想要的是一个视图,这样用户可以只执行 SELECT the_date FROM some_view
并获得结果。我不会事先知道名称或列数,所以这就是我寻求动态 SQL 解决方案的原因。
如果您希望代码 return rows_processed 变量的值,请使用下面的代码 return 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;
" I will not know the names or number of columns in advance, so that's why I'm after a dynamic SQL solution"
这在 SQL 中很难实现:SQL 完全是关于数据结构的,它确实希望列预先存在。所以你不能在 mutable 数据结构上构建 VIEW。
您可以实现 returns 引用游标的功能。这是一个指向可以被客户端解释的数据结构的指针,比如 JDBC ResultSet。
这是一个示例函数,它采用 table 名称和列名称,组合查询和 returns 它的结果集。
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。
我知道这可能不是您正在寻找的解决方案。如果是这种情况,请编辑您的问题以提供有关您要解决的问题的更多详细信息。