函数 returns oracle 中没有任何内容

Function returns nothing in oracle

我创建了一个函数:

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;

当我测试这个函数时 returns 没有任何输出:

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" 语句时,它工作正常并且 returns 连接字符串:

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;

为什么会这样?

您的函数正在查询 ALL_TAB_COLUMNS 视图以查找特定用户拥有的 table,这可能与函数本身所在的架构不同,您看不到table 该函数中的列。但是当你直接或在匿名块中查询ALL_TAB_COLUMNS时,你可以看到table列。

这意味着您的架构对您正在寻找的 table 具有通过角色授予的 select 权限。在命名的 PL/SQL 块中不接受此类权限。如果你在 运行 select ... into 版本之前执行 set role none,你将能够看到同样的事情; table 不会出现在 ALL_TAB_COLUMNS 中,因为您将不再有查询它的权限。

您可以使函数使用 invoker's rights 而不是默认定义者的权限:

create or replace function get_columns
(v_table_name IN varchar2)
RETURN VARCHAR2
AUTHID CURRENT_USER
AS
...

... 但是您依赖调用者直接或通过角色有权查看 table。这可能不是一件坏事 - 如果调用者没有 table 的 select 权限,也许你也不希望他们能够看到它的结构。

您也可以将 table 的权限直接授予函数所有者,但您必须为每一个 table 执行此操作,您希望其他人能够通过该函数查看,这可能会很痛苦,失去角色的优势。

查询 DBA_TAB_COLUMNS 可能更简单,并让您的 DBA 授予您必要的权限,以便您能够查看该视图(如果您还不能的话)。然后,您将不会被限制在您拥有直接 select 权限的 table 中。