测试在 DataGrip 中返回 sys-refcursor 的 Oracle 函数

Posted

技术标签:

【中文标题】测试在 DataGrip 中返回 sys-refcursor 的 Oracle 函数【英文标题】:Testing Oracle function which returns a sys-refcursor in DataGrip 【发布时间】:2020-08-07 15:49:00 【问题描述】:

我有这个任务来实现一个 Oracle 函数来返回对书籍的搜索。我已经把它全部编码了,但我正在努力弄清楚如何最好地测试这个功能。虽然它作为一个过程可能会更好,但规范需要一个函数。这是我要测试的代码:

  FUNCTION SEARCH_BOOK(PI_TITLE_KEYWORD IN          TRNG_BOOK.TITLE%TYPE DEFAULT NULL,
                       PI_PUBLISH_DT_LOWER_BOUND IN TRNG_BOOK.PUBLISH_DT%TYPE DEFAULT NULL,
                       PI_PUBLISH_DT_UPPER_BOUND IN TRNG_BOOK.PUBLISH_DT%TYPE DEFAULT NULL,
                       PI_GENRE_NAME IN             TRNG_GENRE.GENRE_NM%TYPE DEFAULT NULL)
    RETURN SYS_REFCURSOR
    IS
    PO_RESULT SYS_REFCURSOR;
  BEGIN

    OPEN PO_RESULT FOR
      WITH
        LATE_SHIPMENTS_COUNT_LST AS (
          SELECT
            I.BOOK_ID,
            COUNT(*) AS COUNT
          FROM
            TRNG_ORDR_ITEM I
              LEFT OUTER JOIN TRNG_ORDR O ON O.ORDR_ID = I.ORDR_ID
          WHERE
            EXTRACT(DAY FROM COALESCE(O.SHPMT_TSTP, SYSDATE) - O.ORDR_TSTP) > 2
          GROUP BY I.BOOK_ID
        )
      SELECT
        B.BOOK_ID                AS BOOK_ID,
        B.ISBN                   AS ISBN,
        B.TITLE                  AS TITLE,
        B.PUBLISH_DATE           AS PUBLISH_DATE,
        B.PUBLISHER_NAME         AS PUBLISHER_NAME,
        B.COST                   AS COST,
        B.RETAIL_PRICE           AS RETAIL_PRICE,
        B.GENRE_NAME             AS GENRE_NAME,
        B.AUTHOR_LIST            AS AUTHOR_LIST,
        B.TOTAL_QUANTITY_ORDERED AS TOTAL_QUANTITY_ORDERED,
        COALESCE(SC.COUNT, 0)    AS LATE_SHIPMENTS_COUNT
      FROM
        TRNG_BOOK_DETAIL_VW B
          LEFT OUTER JOIN LATE_SHIPMENTS_COUNT_LST SC ON B.BOOK_ID = SC.BOOK_ID
      WHERE
          (PI_TITLE_KEYWORD IS NULL OR B.TITLE IN '%' || PI_TITLE_KEYWORD || '%')
      AND (PI_PUBLISH_DT_LOWER_BOUND IS NULL OR PI_PUBLISH_DT_LOWER_BOUND < B.PUBLISH_DATE)
      AND (PI_PUBLISH_DT_UPPER_BOUND IS NULL OR PI_PUBLISH_DT_UPPER_BOUND > B.PUBLISH_DATE)
      AND (PI_GENRE_NAME IS NULL OR B.GENRE_NAME IN '%' || PI_GENRE_NAME || '%');

    RETURN PO_RESULT;
  END SEARCH_BOOK;

我试图用这个来调用它,它运行没有错误,但没有输出。我想知道......无需花费数小时编写代码,我怎样才能获得某种类型的输出?作为记录,我正在使用 DataGrip。

DECLARE
  RESULT                    SYS_REFCURSOR;
  PI_TITLE_KEYWORD          VARCHAR2(4000) := NULL ;
  PI_PUBLISH_DT_LOWER_BOUND DATE           := NULL ;
  PI_PUBLISH_DT_UPPER_BOUND DATE           := NULL ;
  PI_GENRE_NAME             VARCHAR2(4000) := NULL ;
BEGIN
  RESULT := TRNG_BOOKS.SEARCH_BOOK(
      PI_TITLE_KEYWORD => PI_TITLE_KEYWORD,
      PI_PUBLISH_DT_LOWER_BOUND => PI_PUBLISH_DT_LOWER_BOUND,
      PI_PUBLISH_DT_UPPER_BOUND => PI_PUBLISH_DT_UPPER_BOUND,
      PI_GENRE_NAME => PI_GENRE_NAME
    );

END;

【问题讨论】:

【参考方案1】:

您的 Oracle 版本是什么?

在实际支持的版本中可以使用dbms_sql.return_result():


DECLARE
  RESULT                    SYS_REFCURSOR;
  PI_TITLE_KEYWORD          VARCHAR2(4000) := NULL ;
  PI_PUBLISH_DT_LOWER_BOUND DATE           := NULL ;
  PI_PUBLISH_DT_UPPER_BOUND DATE           := NULL ;
  PI_GENRE_NAME             VARCHAR2(4000) := NULL ;
BEGIN
  RESULT := TRNG_BOOKS.SEARCH_BOOK(
      PI_TITLE_KEYWORD => PI_TITLE_KEYWORD,
      PI_PUBLISH_DT_LOWER_BOUND => PI_PUBLISH_DT_LOWER_BOUND,
      PI_PUBLISH_DT_UPPER_BOUND => PI_PUBLISH_DT_UPPER_BOUND,
      PI_GENRE_NAME => PI_GENRE_NAME
    );
   dbms_sql.return_result(RESULT);
END;

【讨论】:

根据数据库,它是19.6.0.0.0版本。我尝试添加 dbms_sql.return_result(RESULT); 并且我只是得到 [99999][17283] 没有可用的结果集,但正如@Kumar 所说,我正在使用 DataGrip IDE。 【参考方案2】:

你的基础是正确的;您的代码应该按原样运行。您在获得结果后缺少验证。从函数返回后最简单的迭代 ref 光标。但为此,您需要定义一个变量来在迭代时保存这些值。

declare
  type book_search_rec is record 
       ( book_id                  trng_book_detail_vw.book_id%type
       , isbn                     trng_book_detail_vw.isbn%type
       , title                    trng_book_detail_vw.title%type
       , publish_date             trng_book_detail_vw.publish_date%type
       , publisher_name           trng_book_detail_vw.publisher_name%type
       , cost                     trng_book_detail_vw.cost%type
       , retail_price             trng_book_detail_vw.retail_price%type
       , genre_name               trng_book_detail_vw.genre_name%type
       , author_list              trng_book_detail_vw.author_list%type
       , total_quantity_ordered   trng_book_detail_vw.total_quantity_ordered%type
       , late_shipments_count     interger
       );
  po_rec                    book_search_rec;  

  result                    sys_refcursor;
  pi_title_keyword          varchar2(4000) := null ;
  pi_publish_dt_lower_bound date           := null ;
  pi_publish_dt_upper_bound date           := null ;
  pi_genre_name             varchar2(4000) := null ;
  
  
begin
  result := trng_books.search_book(
      pi_title_keyword          => pi_title_keyword,
      pi_publish_dt_lower_bound => pi_publish_dt_lower_bound,
      pi_publish_dt_upper_bound => pi_publish_dt_upper_bound,
      pi_genre_name             => pi_genre_name
    );

  loop
    fetch result into po_rec;
    exit when result%notfound;
    
    dbms_output.put_line( 'Book Id: ' ||  po_rec.book_id); 
    dbms_output.put_line( '   ISBN: ' ||  po_rec.isbn;
    dbms_output.put_line( '  TITLE: ' ||  po_rec.title;
    .
    .
    .
    dbms_output.put_line( 'Late Shipments: ' ||  po_rec.late_shipments_count;
  end loop;              
end; 

          

【讨论】:

以上是关于测试在 DataGrip 中返回 sys-refcursor 的 Oracle 函数的主要内容,如果未能解决你的问题,请参考以下文章

将 .csv 文件导入 Datagrip?

更改 Datagrip 中的命名约定

DataGrip连接Hive

使用 DataGrip 连接到 AWS MySQL 时遇到问题

更新语句使 Datagrip 抱怨缺少 WHERE 子句

在 Datagrip 上更改一个数据源的属性也会更改其他数据源的属性