测试在 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 函数的主要内容,如果未能解决你的问题,请参考以下文章