在PL / SQL中将订单日期标识为存储功能

时间:2019-03-11 00:51:05

标签: sql oracle function plsql

代码:

CREATE OR REPLACE FUNCTION DAY_ORD_SF 
(
  P_DATE_CREATED IN bb_basket.dtcreated%type 
)
RETURN DATE AS
    lv_date_created bb_basket.dtcreated%type;
BEGIN
    SELECT to_char(to_date(P_DATE_CREATED,'yyyy-mm-dd'),'DAY') DAY_CREATED
        INTO lv_date_created
    FROM BB_BASKET
    WHERE lv_date_created <= sysdate
    ORDER BY lv_date_created ASC;
RETURN lv_date_created;
END DAY_ORD_SF;
/

SELECT IDBASKET, dtcreated date_created, to_char(DTCREATED,'DAY') DAY_CREATED, day_ord_sf(dtcreated) weekday_created
FROM BB_BASKET
order by DTCREATED asc;

这是我作为练习存储功能的任务而正在处理的功能。我真的快要完成此问题了,但是却遇到了找不到数据的错误。我不是真的理解此错误,因为当我自己运行代码时,它可以工作。基本上,该函数假定获取日期并返回varchar2数据类型。在将那段代码添加到函数中之前,我确实没有“ to_date(...,'yyyy-mm-dd'),..”。 此任务的第一部分是创建一个SELECT语句,该语句列出每个购物篮的购物篮ID和工作日,第二部分是创建SELECT语句,使用GROUP BY子句列出每个工作日的购物篮总数。根据结果​​,什么是最受欢迎的购物日?我也忘了问,如果您能告诉我为什么我收到“找不到数据”错误,将不胜感激!

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

好吧,这里似乎有多个问题。

让我们开始没有发现数据问题。如果在select语句中使用INTO且select不返回任何行,则会出现未找到数据的异常。这可以通过内部带有异常处理程序的anonyme begin end块来处理,但我认为并非如此。例如:

declare
  v_value number;
begin
  select null
    into v_value
    from dual
   where 1=2; 
exception 
  when NO_DATA_FOUND then
    null; -- Ignore exception and continue
end;

永远不会满足条件1 = 2,因此选择始终不返回任何行,这将始终不会产生未找到数据的错误。使用异常处理程序,我们可以决定下一步要做什么。在此示例中,Null无效。

返回到函数,您的条件是,如果变量lv_date_created小于或等于当前日期,则执行某项操作。这将永远无法工作,因为lv_date_created在执行时等于null。它只是在您的函数中声明,然后在您的选择中使用。这将始终导致false,因此select将始终不返回任何行,也不会找到任何数据。

您还提到要让函数返回varchar2,但定义说它返回日期。同样,变量lv_date_created的类型为date,并且返回该变量,并用varchar2值填充该变量,因此显然Oracle正在对该值进行一些不受控制的转换,不会引发预期数据类型的异常。

条件lv_date_created <= sysdate也可能表明select将找到多个值,如果使用INTO,如果找到多个行,这将导致太多的行异常。

现在让我们来修复此功能。主要问题是您是否需要选择其中的某些内容。通常选择类似的选项来检查表中的条目是否存在,并且没有发现数据异常会告诉我们该条目不存在。如果它是用于数据库中多个位置的通用功能,那么我认为不需要select。我将以这两种解决方案为例。

请注意,对于第一个,您不应再提供dtcreated的colume而是idbasket。

CREATE OR REPLACE FUNCTION DAY_ORD_SF 
(
  P_IDBASKET IN bb_basket.idbasket%type 
)
RETURN VARCHAR2 AS
    lv_date_created VARCHAR2(240);
BEGIN
    SELECT to_char(dtcreated,'DAY') DAY_CREATED
        INTO lv_date_created
    FROM BB_BASKET
    WHERE IDBASKET = P_IDBASKET;
RETURN lv_date_created;
END DAY_ORD_SF;
/

CREATE OR REPLACE FUNCTION DAY_ORD_SF 
(
  P_DATE_CREATED IN bb_basket.dtcreated%type 
)
RETURN VARCHAR2 AS
BEGIN
RETURN to_char(P_DATE_CREATED,'DAY');
END DAY_ORD_SF;
/