【问题标题】:rewriting sql query to pl/sql in oracle apex在 oracle apex 中将 sql 查询重写为 pl/sql
【发布时间】: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

【问题讨论】:

    标签: oracle plsql oracle-apex


    【解决方案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 元素交互
    • 是的。印刷只是为了演示目的。在循环中,您可以使用任何需要的代码操作。
    猜你喜欢
    • 2019-06-30
    • 2012-10-26
    • 2022-01-01
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-29
    • 1970-01-01
    相关资源
    最近更新 更多