在 oracle apex 中将 sql 查询重写为 pl/sql
Posted
技术标签:
【中文标题】在 oracle apex 中将 sql 查询重写为 pl/sql【英文标题】:rewriting sql query to pl/sql in oracle apex 【发布时间】:2021-04-29 16:44:40 【问题描述】:我在 oracle apex 中有一个应用程序,其中有一个名为 search_result 的部分,它返回此 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;
然后我尝试在pl/sql返回sql查询块中返回这个游标:
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
【问题讨论】:
【参考方案1】:当使用 PL/SQL Function Body returning SQL Query
类型时,您需要将 SQL 语句作为字符串返回。所以你所在地区的来源应该是这样的:
BEGIN
return 'SELECT * FROM MOVIES';
END;
使用您在 cmets 中提供的选择,您需要使用两个单引号来表示您返回的字符串中的一个引号。
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;
【讨论】:
我试过这样做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;
但它会抛出此错误 ORA-06550:第 7 行,第 4 列:PLS-00103:在预期以下之一时遇到符号“HTTPS”:* & = - + ; > at in is mod 余数 not rem )> or != or ~= >= and or like like2 like4 likec between ||多集成员子多集**
您选择的语法不正确。您需要在查询中的字符串周围使用''
而不是'
。查看更新的答案。【参考方案2】:
您的代码大部分是正确的。但是,您已将其编写为匿名块,遗憾的是无法返回结果。您需要转换为返回 reference cursor 的函数或带有引用游标的 out 参数的过程。
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;
因为您当前的代码似乎处理的是列列表而不是选择 *。在这种情况下,您可以使用您拥有的确切查询进行选择。
处理:
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;
函数被编译并存储在数据库中(存储过程)。 ref-cursor 是查询的结果集 - 正如您的 Apex 部分不通过查询的结果集返回查询一样。
如何充分使用参考光标。 (主要是)。响应错误类型异常。 此错误是由于您的查询返回的列与表中定义的列不同,但随后尝试获取定义为 movies%rowtype 的变量;现在该定义创建了一个与表列定义完全匹配的结构。但是,您的查询至少有 4 个不属于表定义的列,可能还有 3 个其他列。 Title、Production_Company 和 Poster_Path 列在查询中分别使用了两次。即使有别名,它们仍然代表结果集中的一个附加列。有函数调用和空选择。此外,表中似乎还有其他列不在查询中。这不会使查询出错,只是它无法匹配movies%rowtype 声明。 想到了两个解决方案。只需“从电影中选择 *”并获取 movies%rowtype 声明并在检索表数据后派生其他列。另一种是在包规范中设置适当的游标定义。它可以在包的外部引用。问题是当您实际打开参考游标时,您基本上需要在正文中重复该查询。 假设您确实需要这些列,并且您有不想选择的表列,因为您不需要它们(我喜欢那部分),我整理了一个full demo。因为我没有你的表定义,而且我完全不知道函数 apex_string.get_initials 是什么,所以我只是为他们做了一些事情。但它们似乎是合理的,你应该用实际替换。
【讨论】:
所以我需要创建单独的函数,它将在我的数据库中返回这个查询,然后在这个 pl/sql 函数体中返回它,对吧? 不完全,我已经更新了答案以显示它是如何使用的,但是它涉及一个单独的功能? 基本上,我应该使用我在 sql 查询中使用的自己的查询在我的数据库中创建这个函数,然后在pl/sql function body returning SQL query
中编写这个 processing 代码?
据我所知,我应该返回而不是仅仅打印这个光标以便与 html 元素交互
是的。印刷只是为了演示目的。在循环中,您可以使用任何需要的代码操作。以上是关于在 oracle apex 中将 sql 查询重写为 pl/sql的主要内容,如果未能解决你的问题,请参考以下文章
不能在 sql 查询 APEX ORACLE 中使用绑定变量作为表名
如何在 oracle apex 18 中编辑交互式网格(带有复杂的 sql 查询)?
Oracle APEX - 将隐藏的 SQL 查询下载到 CSV