PL/SQL 如何 return 通过创建或替换函数创建用户定义的记录

PL/SQL how to return a User-Defined Record from create or replace function

我正在努力学习PL/SQL 而且我似乎不明白如何创建一个函数并让它 return a Record

我正在尝试做这样的事情:

create or replace FUNCTION getMovie(movieID number)
RETURN record IS titleAndYear record(title varchar(100), production_Year number);
BEGIN
  if (titleAndYear is null) then
    titleAndYear:= MovieTitleAndYear('',0);
  end if;
  select TITLE ,YEAR into titleAndYear.title ,titleAndYear.production_Year from movie where MOVIE_ID = movieID;
  return titleAndYear;
END;

我知道这不起作用,但我不知道为什么?

编辑 1: 我也试过这个:

create or replace TYPE MovieTitleAndYear is OBJECT(title varchar(100), production_Year number);
/
create or replace FUNCTION getMovie(movieID number)
RETURN MovieTitleAndYear IS titleAndYear MovieTitleAndYear;
BEGIN
  if (titleAndYear is null) then
    titleAndYear:= MovieTitleAndYear('',0);
  end if;
  select TITLE ,YEAR into titleAndYear.title ,titleAndYear.production_Year from movie where MOVIE_ID = movieID;
  return titleAndYear;
END;

但是当我运行这个语句的结果是:

select 
GETMOVIE(
2540943 
) from dual;

变成这样

  GETMOVIE(2540943)
1 [DB_036.MOVIETITLEANDYEAR]

而不是 title 和 productionyear 两列。

您使用记录的第一个示例将不起作用。首先,函数不能 return 仅在函数内部声明的类型的值。您可以尝试将记录类型声明移动到包中,但即使您随后获得了要编译的函数,运行 查询 select getMovie(2540943) from dual 也会 return 一个 ORA-00902 invalid datatype 错误。

所以我建议您改用类型。

如果您使用的是类型,那么要分别获取电影和年份,您需要单独访问类型中的字段,例如:

select getMovie(2540943).title, getMovie(2540943).production_year from dual

或者,如果您想避免调用 getMovie() 两次,您可以使用子查询:

select x.movie_info.title, x.movie_info.production_year from (select getMovie(2540943) as movie_info from dual) x;

注意我们需要为子查询使用别名。以下将给出 ORA-00904: "MOVIE_INFO"."PRODUCTION_YEAR": invalid identifier 错误:

select movie_info.title, movie_info.production_year from (select getMovie(2540943) as movie_info from dual);

这里的问题是 Oracle 正在查询中寻找 table movie_info,但找不到。它没有意识到 movie_info 实际上是一个列。如果我们引入别名​​ x,Oracle 就会意识到 x.movie_info 是一个列,因此 x.movie_info.title 是该列中类型中的一个字段。

Try this approach. I think your answer lies within this snippet. Let me know if this helps.

--Create object type
CREATE OR REPLACE type av_obj_test
IS
  object
  (
    col1 VARCHAR2(100),
    col2 VARCHAR2(100) );


--C reate table type    
CREATE OR REPLACE type av_ntt_test
IS
  TABLE OF av_obj_test;


--Createfunction
CREATE OR REPLACE FUNCTION AV_RECORD RETURN 
AV_NTT_TEST
AS
av_record av_ntt_test;
BEGIN
NULL;
SELECT av_obj_test(LEVEL,'av'||LEVEL) BULK COLLECT INTO av_record FROM DUAL
CONNECT BY LEVEL < 10;
RETURN av_record;
END;


--Calling function
SELECT * FROM TABLE(AV_RECORD);

--------------------------------OUTPUT-------------------------------------

COL1    COL2
1       av1
2       av2
3       av3
4       av4
5       av5
6       av6
7       av7
8       av8
9       av9


-------------------------------OUTPUT----------------------------------------