oracle - 未在规范中声明就无法调用 Oracle 包函数

标签 oracle plsql

下面的例子定义了两个函数,F1F2F1 调用 F2 并使用其结果。我想通过在包规范中声明它来仅公开访问 F1,并使 F2 对包私有(private)。

CREATE OR REPLACE PACKAGE PBL1 AS     
  TYPE t_record IS RECORD(
         foo NUMBER
    );

    TYPE t_table IS TABLE OF t_record;

    FUNCTION F1 RETURN t_table PIPELINED;
END PBL1;

CREATE OR REPLACE PACKAGE BODY PBL1 AS
  FUNCTION F2 RETURN t_table PIPELINED AS
    r t_record;
  BEGIN
    r.foo := 17;
    PIPE ROW (r);
  END F2;

  FUNCTION F1 RETURN t_table PIPELINED AS
  BEGIN
    FOR x IN (SELECT * FROM F2())
    LOOP
        PIPE ROW (x);
    END LOOP;
  END F1;
END PBL1;

如果我尝试按原样编译包体,我会收到错误消息

PL/SQL: SQL Statement ignored
PL/SQL: ORA-00904: invalid ID
PL/SQL: PLS-000231: Function 'F2' may not be be used in SQL

如果我将 F2 添加到包规范中,错误就会消失,我想避免这种情况。

我在 answer to this question 中读到这可能是由于上下文切换到 SQL 上下文,它只知道公共(public)包函数,而不是 PL/SQL 上下文,它知道私有(private)包内容。但是这个问题的提问者并没有提供示例代码,而且回答者似乎也收回了答案,所以我还是想提出这个问题。

有没有一种方法可以从其他函数调用包私有(private)函数而不需要在包的公共(public)规范中公开它们?

最佳答案

无法在 SQL 中使用私有(private) PL/SQL 函数。即使当 SQL 语句嵌入到与该私有(private)函数相同的包主体中的代码中时,情况仍然如此。在这种讨论中,“上下文切换”这个词被广泛使用(我自己过去也做过一些使用),但这是一种粗略的简化,更不用说扭曲了。但基本原则仍然如您所说:

[SQL] only knows about public package functions

所以问题变成了:您的(真实的)F2() 函数必须是流水线的吗?你不能只填充一个嵌套表吗?通过该实现,F1() 可以调用 F2(),然后循环访问返回的表。像这样:

CREATE OR REPLACE PACKAGE PBL1 AS     
  TYPE t_record IS RECORD(
         foo NUMBER);

    TYPE t_table IS TABLE OF t_record;

    FUNCTION F1 RETURN t_table PIPELINED;

END PBL1;
/
CREATE OR REPLACE PACKAGE BODY PBL1 AS

  FUNCTION F2 RETURN t_table AS
    r t_record;
    t t_table := new t_table() ;
  BEGIN
    r.foo := 17;
    t.extend();
    t(1) := r;

    return t;    
  END F2;

  FUNCTION F1 RETURN t_table PIPELINED AS
    r t_record;    
    t t_table;
  BEGIN
    t := f2;

    FOR x IN 1 .. t.count()
    LOOP
        r := t(x);    
        PIPE ROW (r);
    END LOOP;

  END F1;
END PBL1;
/

显然这可能不是您正在寻找的解决方案,但这是我在不知道您的基本要求的情况下所能做的最好的解决方案。

关于oracle - 未在规范中声明就无法调用 Oracle 包函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58914253/

相关文章:

oracle - SQL插入语句返回 "zero/no rows inserted"

oracle - 如何在文件系统上创建目录?

plsql - 在 plsql 过程中创建表时出错

Oracle pl/sql脚本,递增数字

oracle - 如何将hadoop数据存储到oracle中

oracle - Oracle 中的 "Bulk Collect Into"和 "Execute Immediate"

Oracle:插入时不指定列

sql - PL/SQL varchar(10)到varchar(9)

使用动态 SQL ALTER USER 查询的 SQL 注入(inject)预防

oracle - PL/SQL存储过程创建表