在选择中使用函数中的行类型 - PL SQL

Posted

技术标签:

【中文标题】在选择中使用函数中的行类型 - PL SQL【英文标题】:Use rowtype from function in select - PL SQL 【发布时间】:2021-09-09 08:34:12 【问题描述】:

我有以下功能-

  function f_get_emp_details(i_emp_no in t_emp.emp_no) return t_emp%rowtype is 
       l_emp_row t_emp%rowtype;
    Begin
      select *
      into l_emp_row
      from t_emp
      where t_emp.emp_no = i_emp_no;
    
    return l_emp_row;

    exception when others then
           return null;
    end;

我在其他程序中有一个光标-

    open c_tasks
      select task_id, 
             task_name,
             f_get_emp_details(t_task.emp_no)
      from t_task;

如何在选择中使用该功能?我需要函数中使用的多个字段。

【问题讨论】:

请编辑您的问题以提供minimal reproducible example。在光标中使用函数而不是仅仅加入t_emp 表有什么好处? ***.com/q/1020348/1509264 的可能重复项(因为 %ROWTYPE 隐含地是一种记录类型)。但是,如果您将其设为返回记录表的 PIPELINED 函数,则根据您的 Oracle 版本,它可能会起作用(根据 this answer 对同一问题)。 【参考方案1】:

如果你真的想用这种方式得到复杂的类型,你需要使用对象类型,像这样:

create or replace type t_emp_type is object(
  id     int,
  emp_no int,
  extra  varchar2(30)
);

完整示例:和DBFiddle:https://dbfiddle.uk/?rdbms=oracle_18&fiddle=af691e479236dc3f5b7e15e14fed5ba0

create table t_emp(
  id     int,
  emp_no int,
  extra  varchar2(30)
);
create table t_task(
  task_id   int, 
  task_name varchar2(30),
  emp_no    int
);
insert into t_emp
  select level-1,level-1,'extra #'||(level-1)
  from dual
  connect by level<=10;
insert into t_task
  select level, 'task #'||level, mod(level,10) as emp_no
  from dual
  connect by level<=30;

create or replace type t_emp_type is object(
  id     int,
  emp_no int,
  extra  varchar2(30)
);

create or replace
  function f_get_emp_details(i_emp_no in t_emp.emp_no%type) return t_emp_type is 
       l_emp_row t_emp%rowtype;
    Begin
      select *
      into l_emp_row
      from t_emp
      where t_emp.emp_no = i_emp_no;
    
    return t_emp_type(l_emp_row.id, l_emp_row.emp_no, l_emp_row.extra);
    end;
/
select task_id, 
       task_name,
       (emp_details).id,
       (emp_details).emp_no,
       (emp_details).extra
from (
  select task_id, 
         task_name,
         f_get_emp_details(t_task.emp_no) emp_details
  from t_task
);

结果:

   TASK_ID TASK_NAME       (EMP_DETAILS).ID (EMP_DETAILS).EMP_NO (EMP_DETAILS).EXTRA
---------- --------------- ---------------- -------------------- --------------------
         1 task #1                        1                    1 extra #1
         2 task #2                        2                    2 extra #2
         3 task #3                        3                    3 extra #3
         4 task #4                        4                    4 extra #4
         5 task #5                        5                    5 extra #5
         6 task #6                        6                    6 extra #6
         7 task #7                        7                    7 extra #7
         8 task #8                        8                    8 extra #8
         9 task #9                        9                    9 extra #9
        10 task #10                       0                    0 extra #0
        11 task #11                       1                    1 extra #1
        12 task #12                       2                    2 extra #2
        13 task #13                       3                    3 extra #3
        14 task #14                       4                    4 extra #4
        15 task #15                       5                    5 extra #5
        16 task #16                       6                    6 extra #6
        17 task #17                       7                    7 extra #7
        18 task #18                       8                    8 extra #8
        19 task #19                       9                    9 extra #9
        20 task #20                       0                    0 extra #0
        21 task #21                       1                    1 extra #1
        22 task #22                       2                    2 extra #2
        23 task #23                       3                    3 extra #3
        24 task #24                       4                    4 extra #4
        25 task #25                       5                    5 extra #5
        26 task #26                       6                    6 extra #6
        27 task #27                       7                    7 extra #7
        28 task #28                       8                    8 extra #8
        29 task #29                       9                    9 extra #9
        30 task #30                       0                    0 extra #0

30 rows selected.

【讨论】:

以上是关于在选择中使用函数中的行类型 - PL SQL的主要内容,如果未能解决你的问题,请参考以下文章

选择 PL/SQL 中两个非空列值之间的行集

如何在选择语句的“NOT IN”子句中使用逗号分隔的字符串列表作为 pl/sql 存储的函数参数

在 oracle pl/sql 中如何选择嵌套类型?

如何创建一个 Oracle 全局类型并在 PL/SQL 中使用它?

plsql使用教程

带有参数的 PL/SQL 过程/函数从选择查询返回表