【问题标题】:Function return sys_refcursor call from sql with specific columns函数从具有特定列的 sql 返回 sys_refcursor 调用
【发布时间】:2012-11-21 07:46:09
【问题描述】:

这可能有点傻,但我想知道这是否可能。

我有一个返回 sys_refcursor 的函数

CREATE OR REPLACE FUNCTION get_employee_details(p_emp_no IN EMP.EMPNO%TYPE)
   RETURN SYS_REFCURSOR
AS
   o_cursor   SYS_REFCURSOR;
BEGIN
   OPEN o_cursor FOR
      SELECT EMPNO,
             ENAME,
             JOB,
             MGR,
             HIREDATE,
             SAL,
             COMM,
             DEPTNO
        FROM emp
       WHERE EMPNO = p_emp_no;

   RETURN o_cursor;
 -- exception part
END;
/

我可以使用

得到结果
select  get_employee_details('7369') from dual;

是否可以通过指定列名从上述函数中获取结果? 例如。如果我想获得姓名或薪水,如何在不使用 plsql 块的情况下在 sql 语句中指定? 像

select  get_employee_details('7369') <specific column> from dual;

【问题讨论】:

  • @NicholasKrasnov 这背后的想法是我将创建一个用于获取员工详细信息的函数,当我只想获取员工的薪水时,是否可以指定仅获取薪水而不是所有列? select get_employee_details('7369') from dual 将返回函数选择列列表中指定的所有列。

标签: sql function plsql oracle10g sys-refcursor


【解决方案1】:

为此,您可能需要查看PIPELINED 函数。不过,您必须在 PL/SQL 级别声明显式类型。该部分将设置输出列名:

CREATE OR REPLACE TYPE my_rec AS OBJECT (
  c CHAR,
  n NUMBER(1)
);

CREATE OR REPLACE TYPE my_tbl AS TABLE OF my_rec;

现在,最大的优势是您不仅可以“重命名”列,还可以通过光标即时修改记录。例如:

CREATE OR REPLACE FUNCTION my_fct
RETURN my_tbl PIPELINED
AS
  -- dummy data - use your own cursor here
  CURSOR data IS
      SELECT 'a' as A, 1 AS B FROM DUAL UNION 
      SELECT 'b', 2 FROM DUAL UNION 
      SELECT 'c', 3 FROM DUAL UNION 
      SELECT 'd', 4 FROM DUAL;
BEGIN
  FOR the_row IN data
  LOOP 
      PIPE ROW(my_rec(the_row.a, the_row.b*2));
      --                                  ^^
      --                            Change data on the fly
  END LOOP;
END

用法:

SELECT * FROM TABLE(my_fct())
--            ^^^^^^^^^^^^^^^
--     Use this "virtual" table like any
--     other table. Supporting `WHERE`  clause
--     or any other SELECT clause you want

制作:

C   N
a   2
b   4
c   6
d   8

【讨论】:

  • 感谢您的解决方案。
  • @Polppan :D 我什至不希望你会在这么长时间后看看它!我很高兴你能欣赏它。
  • 谢谢!非常有帮助并且非常清楚地显示出来。我很少使用 Oracle,需要一些很好的示例来进行测试。
【解决方案2】:

不,根本不使用ref cursor,否则不创建 SQL 类型以将返回值转换为,例如:http://dbaspot.com/oracle-server/9308-select-ref-cursor.html

create or replace type myType as object (
a int,
b varchar2(10)
)
/

create or replace type myTable as table of myType;
/

create or replace function f1 return myTable as
l_data myTable := myTable();
begin
for i in 1 .. 5 loop
l_data.extend;
l_data(i) := myType(i, 'Row #'||i );
end loop;
return l_data;
end;
/

select * from TABLE ( cast( f1() as myTable ) );

---------- ----------
1 Row #1
2 Row #2
3 Row #3
4 Row #4
5 Row #5

来自该主题的最后一篇文章:

您已经知道的方式是唯一可以使用的方式 select 语句中的 REF CURSOR。

【讨论】:

  • 不太明白这个? the way you already knew about is the only one to use the REF CURSOR in a select statement.
  • 如果您阅读链接中的整个线程,这很有意义;) 基本上,select get_employee_details('7369') from dual 是您获得 SQL 的全部内容。 ref cursors 并不是真的应该以这种方式使用,它们用于在子程序之间传递(我认为在某些情况下用于客户端库,但不要引用我的话)。
  • 啊,我明白了 :-) 所以引用游标在 sql 语句中的使用只有有限的选项,除非在 plsql 块中使用。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-23
  • 1970-01-01
  • 2021-01-29
  • 2014-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多