Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在SQL中检索PL/SQL记录类型?_Sql_Oracle_Plsql_Oracle12c_User Defined Types - Fatal编程技术网

如何在SQL中检索PL/SQL记录类型?

如何在SQL中检索PL/SQL记录类型?,sql,oracle,plsql,oracle12c,user-defined-types,Sql,Oracle,Plsql,Oracle12c,User Defined Types,存在一个共享包,它定义了一个学生记录类型和一个返回学生的函数: CREATE OR REPLACE PACKAGE shared.student_utils IS --aggregates related data from several tables TYPE student_rec IS RECORD ( id student.id%TYPE, username student.username%TYPE, name student.na

存在一个共享包,它定义了一个学生记录类型和一个返回学生的函数:

CREATE OR REPLACE PACKAGE shared.student_utils IS
  --aggregates related data from several tables
  TYPE student_rec IS RECORD (
    id       student.id%TYPE,
    username student.username%TYPE,
    name     student.name%TYPE,
    phone    phone.phone%TYPE
    /*etc.*/
  );

  FUNCTION get_student(student_id IN student.id%TYPE) RETURN student_rec;
END;
现在,我正在编写一个包,为Apex应用程序提供一个API供其使用。特别是,我需要以可以通过SQL选择的格式提供学生记录和其他相关数据(并显示在Apex的报告页面中)

到目前为止,我一直在试图找到在SQL中选择数据的最直接的方法。显然,SQL中不能使用记录类型,因此我快速而肮脏的想法是在我的包规范中定义一个表类型,在包规范/正文中定义一个管道化的
函数:

CREATE OR REPLACE PACKAGE my_schema.api IS
  TYPE student_tab IS TABLE OF shared.student_utils.student_rec;

  FUNCTION get_all_student_data(student_id IN student.id%TYPE) RETURN student_tab PIPELINED;
END;
/
CREATE OR REPLACE PACKAGE BODY my_schema.api IS
  FUNCTION get_all_student_data(student_id IN student.id%TYPE) RETURN student_tab PIPELINED IS
  BEGIN
    PIPE ROW(shared.student_utils.get_student(student_id));
  END;
END;
…这让我可以这样选择它:

SELECT * FROM TABLE(my_schema.api.get_all_student_data(1234));
这是可行的,但只为一行构建一个流水线表是过分的,Oracle的解释计划似乎也同意这一点

据推测,在Oracle 12c中,应该有更多可用选项:

…但在我的场景中,我似乎无法理解。将功能更改为:

FUNCTION get_all_student_data RETURN student_tab IS
  r_student_tab student_tab;
BEGIN
  r_student_tab(1) := shared.student_utils.get_student(student_id);

  RETURN r_student_tab;
END;
…将编译,但我无法像以前那样从中选择

好了,说得够多了,这是我的实际问题-调用返回记录类型并在SQL中选择/操作结果的PL/SQL函数最直接的方法是什么?

致命的一行是:

PL/SQL函数不能将仅PL/SQL类型的值返回给SQL

这似乎排除了直接从返回PL/SQL记录或关联数组的函数进行查询的可能性,如下所示:

select * from table(student_utils.get_students(7890));
工作原理是这样的,从技术上讲,这是SQL(因为文档将匿名块定义为SQL而不是PL/SQL):

这是相当蹩脚的。我想有几次我们想从数组中打开一个ref游标,而不仅仅是为了填充数组的SQL而打开它,但这并不是最紧迫的用例

问题在于Oracle的内部架构:内核有用于SQL的C模块和用于PL/SQL的C模块(这就是为什么您会听到人们谈论“上下文切换”)。向SQL引擎公开更多PL/SQL功能需要修改接口。我们只能想象,让SQL编译器针对PL/SQL数据结构的定义工作是多么困难,这些数据结构非常不稳定(每次运行
创建或替换包…
时,它们都可能发生变化)


当然,这对流水线函数是有效的,但这是因为Oracle为函数中引用的PL/SQL类型创建SQL类型。它不能为任意函数动态创建对象,我们可能希望滑入
表()有一天,它可能是可行的,但请考虑一下这一点:当一个用户在我们的包上执行但缺少创建类型权限时,会尝试使用这个函数?

这个链接可能会帮助你,我的个人(!)感觉是:您经常在学生书籍和教程中看到Oracle对象类型,它们是许多PL/SQL培训中的一个重要主题。然而,实际上,对象类型很少用于生产性应用程序。“几乎”并不意味着“从不”-但我只是觉得它们在教育中比在生产中更容易处理。@eifla001在更仔细地阅读了您链接的问题后,它似乎完全回答了我的问题。我不知道为什么在我所有的搜索中,我自己从来没有找到过这个问题。希望dupe targeting它能帮助下一个人找到它。+1,谢谢,t他的观点很有道理。那么,在12c中“更多的PL/SQL数据类型可以跨PL/SQL到SQL接口”意味着什么呢?Steven Feuerstein发布了一个LiveSQL演示,介绍了这些更改所带来的新功能。
declare
    ltab student_utils.students_tab;
    lrec student_utils.student_rec;
    rc sys_refcursor;
begin
    ltab := student_utils.get_students(1234);
    open rc for select * from table(ltab);
    fetch rc into lrec;
    dbms_output.put_line(lrec.name);
    close rc;
end;
/