首页 > 解决方案 > 将 PL/SQL 中订单日期的工作日标识为存储函数

问题描述

代码:

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 子句列出每个工作日的篮子总数. 根据结果​​,最受欢迎的购物日是哪一天?另外我忘了问,如果你能告诉我为什么我得到“

谢谢你的协助!

标签: sqloraclefunctionplsql

解决方案


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

让我们从没有发现数据的问题开始。如果您在 select 语句中使用 INTO 并且 select 不返回任何行,您会得到一个 no data found 异常。这可以通过带有异常处理程序的匿名开始结束块来处理,但我相信情况并非如此。例如:

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。它只是在您的函数中声明,然后在您的选择中使用。这将始终导致错误,因此 select 将始终不返回任何行且未找到数据异常。

您还提到您希望函数返回 varchar2 但您的定义说它返回日期。变量 lv_date_created 也是 date 类型,这是返回的变量,你用 varchar2 值填充它,所以显然 Oracle 正在对 this 的值进行一些不受控制的转换,不会引发有关预期数据类型的异常。

此外,条件 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;
/

推荐阅读