我创建了一个函数:
create or replace function get_columns
(v_table_name IN varchar2)
RETURN VARCHAR2
AS
v_columns_list VARCHAR2(2048);
BEGIN
SELECT listagg(column_name,',') WITHIN GROUP (ORDER BY column_name) AS t_list into v_columns_list
FROM ALL_TAB_COLUMNS WHERE owner='MyOwner' AND table_name=v_table_name;
RETURN v_columns_list;
END;
当我测试此函数时,它不会向输出返回任何内容:
declare
v_columns_list varchar2(2048);
v_table_name varchar2(100) := 'MyTable';
begin
-- SELECT listagg(column_name,',') WITHIN GROUP (ORDER BY column_name) AS t_list INTO v_columns_list
-- FROM ALL_TAB_COLUMNS WHERE owner='MyOwner' AND table_name=v_table_name;
v_columns_list := get_columns(v_table_name);
dbms_output.put_line(v_columns_list);
end;
结果:
anonymous block completed
然而,当我测试相同的" SELECT INTO"声明它工作正常并返回连接字符串:
declare
v_columns_list varchar2(2048);
v_table_name varchar2(100) := 'MyTable';
begin
SELECT listagg(column_name,',') WITHIN GROUP (ORDER BY column_name) AS t_list INTO v_columns_list
FROM ALL_TAB_COLUMNS WHERE owner='MyOwner' AND table_name=v_table_name;
-- v_columns_list := get_columns(v_table_name);
dbms_output.put_line(v_columns_list);
end;
为什么会这样?
答案 0 :(得分:1)
您的函数正在查询特定用户拥有的表的ALL_TAB_COLUMNS
视图,这可能与函数本身所在的模式不同,并且您无法查看该函数中的表列。但是,当您直接或在匿名块中查询ALL_TAB_COLUMNS
时,您可以看到表格列。
这意味着您的架构对您通过角色寻找的表格具有选择权限。在命名的PL / SQL块中不支持此类权限。如果您在运行set role none
版本之前select ... into
执行了ALL_TAB_COLUMNS
,则可以看到相同的内容。该表不会出现在create or replace function get_columns
(v_table_name IN varchar2)
RETURN VARCHAR2
AUTHID CURRENT_USER
AS
...
中,因为您将无权再查询它。
您可以使用invoker's rights代替默认定义者的权利:
DBA_TAB_COLUMNS
...但是,您依赖于有权限直接或通过角色查看该表的调用者。这可能不是一件坏事 - 如果来电者没有从表格中选择的权限,也许你不希望他们能够看到它的结构。
你也可以直接向函数所有者授予对表的权限,但是你必须为你希望其他人能够通过该函数查看的每个表执行此操作,这可能是痛苦的并且失去了角色的优势。
查询{{1}}可能更简单,并让您的DBA为您提供必要的权限,以便能够查看该视图(如果您已经不能)。然后,您不会被限制在具有直接选择权限的表格中。