在 oracle apex 中将 sql 查询重写为 pl/sql
rewriting sql query to pl/sql in oracle apex
我在 oracle apex 中有一个应用程序,有一个名为 search_result 的部分,它 return 是这个 sql 查询
select
"TITLE" CARD_TITLE,
"POSTER_PATH" CARD_TEXT,
"PRODUCTION_COMPANY" CARD_SUBTEXT,
apex_string.get_initials("TITLE") CARD_INITIALS,
'https://www.imdb.com/title/'||IMDB_ID CARD_LINK,
null CARD_MODIFIERS,
null CARD_COLOR,
null CARD_ICON,
"GENRE",
"COUNTRY",
"PRODUCTION_COMPANY",
"RUNTIME",
"BUDGET",
"VOTE_AVERAGE",
"TITLE",
"POSTER_PATH"
from "MOVIES"
order by vote_average desc
但我需要用 pl/sql 函数体和
我创建了功能包
CREATE OR REPLACE PACKAGE PRINTS AS
FUNCTION MOVIES_LIST RETURN SYS_REFCURSOR;
FUNCTION ORDER_VOTE RETURN SYS_REFCURSOR;
END PRINTS;
CREATE OR REPLACE PACKAGE BODY PRINTS AS
FUNCTION ORDER_VOTE
RETURN SYS_REFCURSOR
is
r_movie sys_refcursor;
BEGIN
open r_movie for select
"TITLE" CARD_TITLE,
"POSTER_PATH" CARD_TEXT,
"PRODUCTION_COMPANY" CARD_SUBTEXT,
apex_string.get_initials("TITLE") CARD_INITIALS,
null CARD_MODIFIERS,
null CARD_COLOR,
null CARD_ICON,
"GENRE",
"COUNTRY",
"PRODUCTION_COMPANY",
"RUNTIME",
"BUDGET",
"VOTE_AVERAGE",
"TITLE",
"POSTER_PATH"
from "MOVIES"
order by vote_average desc;
return r_movie;
END ORDER_VOTE;
END PRINTS;
然后我尝试 return 在 pl/sql returning sql 查询块中 return 这个游标 :
declare
movie_cur sys_refcursor;
a_movie movies%rowtype;
begin
movie_cur := PRINTS.ORDER_VOTE; -- call the movie function
loop
fetch movie_cur into a_movie;
exit when movie_cur%notfound;
end loop;
return a_movie;
end;
但是它抛出这个错误:
ORA-06550:第 12 行,第 11 列:PLS-00382:表达式类型错误
我做错了什么,我该如何解决。
我的数据库和一些截图:
Column Name Data Type Nullable Default Primary Key
ID NUMBER No "WKSP_DBMSPROJECT1"."ISEQ$$_111377832".nextval 1
TITLE VARCHAR2(255) Yes - -
GENRE VARCHAR2(50) Yes - -
COUNTRY VARCHAR2(50) Yes - -
PRODUCTION_COMPANY VARCHAR2(255) Yes - -
RUNTIME NUMBER Yes - -
RELEASE_DATE DATE Yes - -
OVERVIEW VARCHAR2(4000) Yes - -
TAGLINE VARCHAR2(255) Yes - -
BUDGET NUMBER Yes - -
REVENUE NUMBER Yes - -
POPULARITY NUMBER Yes - -
VOTE_AVERAGE NUMBER Yes - -
VOTE_COUNT NUMBER Yes - -
POSTER_PATH VARCHAR2(255) Yes - -
TMDB_ID NUMBER Yes - -
IMDB_ID VARCHAR2(50) Yes - -
IMDB DB
page design
page itself
当使用 PL/SQL Function Body returning SQL Query
类型时,您需要 return 您的 SQL 语句作为字符串。所以你所在地区的来源应该是这样的:
BEGIN
return 'SELECT * FROM MOVIES';
END;
使用您在评论中提供的 select,您需要使用两个单引号来表示您正在 returning 的字符串中的引号。
BEGIN
RETURN 'SELECT "TITLE" CARD_TITLE,
"POSTER_PATH" CARD_TEXT,
"PRODUCTION_COMPANY" CARD_SUBTEXT,
apex_string.get_initials ("TITLE") CARD_INITIALS,
''https://www.imdb.com/title/'' || IMDB_ID CARD_LINK,
NULL CARD_MODIFIERS,
NULL CARD_COLOR,
NULL CARD_ICON,
"GENRE",
"COUNTRY",
"PRODUCTION_COMPANY",
"RUNTIME",
"BUDGET",
"VOTE_AVERAGE",
"TITLE",
"POSTER_PATH"
FROM "MOVIES"
ORDER BY vote_average DESC';
END;
您的代码大部分是正确的。但是你已经将它写成一个匿名块,不幸的是不能 return 结果。您需要转换为 return 为 reference cursor 的函数或带有参考游标输出参数的过程。
create or replace
function movies_list
return sys_refcursor
is
r_movies sys_refcursor;
begin
open r_movies for
select * from movies;
return r_movies;
end movies_list;
因为您当前的代码似乎处理的是列列表而不是 select *。在这种情况下,您可以 select 使用您的确切查询。
处理中:
declare
movie_cur sys_refcursor;
a_movie movies%rowtype;
begin
dbms_output.enable;
movie_cur := movies_list; -- call the movie function
dbms_output.put_line("Movie List');
loop
fetch movie_cur into a_movie;
exit when movie_cur%not_found;
dbms_output.put_line(a_movie.title);
end loop;
end;
该函数被编译并存储在数据库中(一个存储过程)。 THE ref-cursor 是查询的结果集——就像你的 Apex 部分没有 return 查询一样,通过查询的结果集。
如何完整使用引用游标。 (主要是)。响应错误类型异常。
此错误是由于您的查询 return 与 table 中定义的列不同,但随后试图提取到定义为 movies%rowtype 的变量;现在该定义创建了一个与 tables 列定义完全匹配的结构。但是,您的查询至少有 4 列不属于 table 定义的一部分,可能还有 3 列。 Title、Production_Company 和 Poster_Path 列在查询中各使用了两次。即使使用了别名,它们仍然代表结果集中的一个附加列。有函数调用和空 select 离子。此外,table 中似乎还有其他列不在查询中。这不会使查询变坏,只是它无法匹配 movies%rowtype 声明。
我想到了两种解决方案。只需“select * from movies”并获取到
movies%rowtype 声明并在检索 table 数据后派生附加列。另一种是在包规范中设置适当的游标定义。它可以在包的外部引用。问题是当您实际打开引用游标时,您基本上需要在正文中重复该查询。
假设您确实需要这些列,并且您有 table 列,您希望避免 selecting 因为您不需要它们(我喜欢那部分),我将 full demo 放在一起。由于我没有您的 table 定义,而且我完全不知道 apex_string.get_initials 函数是什么,所以我只是为它们做了一些补充。不过貌似挺有道理的,换成实际应该会出问题。
我在 oracle apex 中有一个应用程序,有一个名为 search_result 的部分,它 return 是这个 sql 查询
select
"TITLE" CARD_TITLE,
"POSTER_PATH" CARD_TEXT,
"PRODUCTION_COMPANY" CARD_SUBTEXT,
apex_string.get_initials("TITLE") CARD_INITIALS,
'https://www.imdb.com/title/'||IMDB_ID CARD_LINK,
null CARD_MODIFIERS,
null CARD_COLOR,
null CARD_ICON,
"GENRE",
"COUNTRY",
"PRODUCTION_COMPANY",
"RUNTIME",
"BUDGET",
"VOTE_AVERAGE",
"TITLE",
"POSTER_PATH"
from "MOVIES"
order by vote_average desc
但我需要用 pl/sql 函数体和 我创建了功能包
CREATE OR REPLACE PACKAGE PRINTS AS
FUNCTION MOVIES_LIST RETURN SYS_REFCURSOR;
FUNCTION ORDER_VOTE RETURN SYS_REFCURSOR;
END PRINTS;
CREATE OR REPLACE PACKAGE BODY PRINTS AS
FUNCTION ORDER_VOTE
RETURN SYS_REFCURSOR
is
r_movie sys_refcursor;
BEGIN
open r_movie for select
"TITLE" CARD_TITLE,
"POSTER_PATH" CARD_TEXT,
"PRODUCTION_COMPANY" CARD_SUBTEXT,
apex_string.get_initials("TITLE") CARD_INITIALS,
null CARD_MODIFIERS,
null CARD_COLOR,
null CARD_ICON,
"GENRE",
"COUNTRY",
"PRODUCTION_COMPANY",
"RUNTIME",
"BUDGET",
"VOTE_AVERAGE",
"TITLE",
"POSTER_PATH"
from "MOVIES"
order by vote_average desc;
return r_movie;
END ORDER_VOTE;
END PRINTS;
然后我尝试 return 在 pl/sql returning sql 查询块中 return 这个游标 :
declare
movie_cur sys_refcursor;
a_movie movies%rowtype;
begin
movie_cur := PRINTS.ORDER_VOTE; -- call the movie function
loop
fetch movie_cur into a_movie;
exit when movie_cur%notfound;
end loop;
return a_movie;
end;
但是它抛出这个错误: ORA-06550:第 12 行,第 11 列:PLS-00382:表达式类型错误
我做错了什么,我该如何解决。
我的数据库和一些截图:
Column Name Data Type Nullable Default Primary Key
ID NUMBER No "WKSP_DBMSPROJECT1"."ISEQ$$_111377832".nextval 1
TITLE VARCHAR2(255) Yes - -
GENRE VARCHAR2(50) Yes - -
COUNTRY VARCHAR2(50) Yes - -
PRODUCTION_COMPANY VARCHAR2(255) Yes - -
RUNTIME NUMBER Yes - -
RELEASE_DATE DATE Yes - -
OVERVIEW VARCHAR2(4000) Yes - -
TAGLINE VARCHAR2(255) Yes - -
BUDGET NUMBER Yes - -
REVENUE NUMBER Yes - -
POPULARITY NUMBER Yes - -
VOTE_AVERAGE NUMBER Yes - -
VOTE_COUNT NUMBER Yes - -
POSTER_PATH VARCHAR2(255) Yes - -
TMDB_ID NUMBER Yes - -
IMDB_ID VARCHAR2(50) Yes - -
IMDB DB
page design
page itself
当使用 PL/SQL Function Body returning SQL Query
类型时,您需要 return 您的 SQL 语句作为字符串。所以你所在地区的来源应该是这样的:
BEGIN
return 'SELECT * FROM MOVIES';
END;
使用您在评论中提供的 select,您需要使用两个单引号来表示您正在 returning 的字符串中的引号。
BEGIN
RETURN 'SELECT "TITLE" CARD_TITLE,
"POSTER_PATH" CARD_TEXT,
"PRODUCTION_COMPANY" CARD_SUBTEXT,
apex_string.get_initials ("TITLE") CARD_INITIALS,
''https://www.imdb.com/title/'' || IMDB_ID CARD_LINK,
NULL CARD_MODIFIERS,
NULL CARD_COLOR,
NULL CARD_ICON,
"GENRE",
"COUNTRY",
"PRODUCTION_COMPANY",
"RUNTIME",
"BUDGET",
"VOTE_AVERAGE",
"TITLE",
"POSTER_PATH"
FROM "MOVIES"
ORDER BY vote_average DESC';
END;
您的代码大部分是正确的。但是你已经将它写成一个匿名块,不幸的是不能 return 结果。您需要转换为 return 为 reference cursor 的函数或带有参考游标输出参数的过程。
create or replace
function movies_list
return sys_refcursor
is
r_movies sys_refcursor;
begin
open r_movies for
select * from movies;
return r_movies;
end movies_list;
因为您当前的代码似乎处理的是列列表而不是 select *。在这种情况下,您可以 select 使用您的确切查询。
处理中:
declare
movie_cur sys_refcursor;
a_movie movies%rowtype;
begin
dbms_output.enable;
movie_cur := movies_list; -- call the movie function
dbms_output.put_line("Movie List');
loop
fetch movie_cur into a_movie;
exit when movie_cur%not_found;
dbms_output.put_line(a_movie.title);
end loop;
end;
该函数被编译并存储在数据库中(一个存储过程)。 THE ref-cursor 是查询的结果集——就像你的 Apex 部分没有 return 查询一样,通过查询的结果集。
如何完整使用引用游标。 (主要是)。响应错误类型异常。
此错误是由于您的查询 return 与 table 中定义的列不同,但随后试图提取到定义为 movies%rowtype 的变量;现在该定义创建了一个与 tables 列定义完全匹配的结构。但是,您的查询至少有 4 列不属于 table 定义的一部分,可能还有 3 列。 Title、Production_Company 和 Poster_Path 列在查询中各使用了两次。即使使用了别名,它们仍然代表结果集中的一个附加列。有函数调用和空 select 离子。此外,table 中似乎还有其他列不在查询中。这不会使查询变坏,只是它无法匹配 movies%rowtype 声明。
我想到了两种解决方案。只需“select * from movies”并获取到
movies%rowtype 声明并在检索 table 数据后派生附加列。另一种是在包规范中设置适当的游标定义。它可以在包的外部引用。问题是当您实际打开引用游标时,您基本上需要在正文中重复该查询。
假设您确实需要这些列,并且您有 table 列,您希望避免 selecting 因为您不需要它们(我喜欢那部分),我将 full demo 放在一起。由于我没有您的 table 定义,而且我完全不知道 apex_string.get_initials 函数是什么,所以我只是为它们做了一些补充。不过貌似挺有道理的,换成实际应该会出问题。