【问题标题】:Identifying the Weekday for an Order Date in PL/SQL as stored function将 PL/SQL 中订单日期的工作日标识为存储函数
【发布时间】:2019-08-01 07:09:34
【问题描述】:

代码:

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 子句列出每个工作日的篮子总数.根据结果​​,最受欢迎的购物日是哪一天?另外我忘了问,如果您能告诉我为什么会收到“未找到数据”错误,将不胜感激!

感谢您帮助我!

【问题讨论】:

标签: sql oracle function plsql


【解决方案1】:

嗯,这里似乎有多个问题。

让我们从没有发现数据的问题开始。如果您在 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。它只是在您的函数中声明,然后在您的选择中使用。这将始终导致 false,因此 select 将始终不返回任何行且未找到数据异常。

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

另外,条件 lv_date_created

现在让我们来修复这个功能。主要问题是您是否需要在其中选择某些内容。选择类似的东西通常用于检查表中的条目是否存在,并且没有发现数据异常会告诉我们条目不存在。如果它是用于数据库中多个位置的通用功能,那么我认为不需要 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;
/

【讨论】:

  • 我想我没有想到,但我应该将它切换为大于或等于 lv_created_date 吗?因为当我使用 p_date_created 时,它现在给我选择了“太多行”。当我使用 lv_created_date 时,查询会弹出,但最后一列的结果给了我“(null)”。有什么想法吗?
  • 我添加了更多关于这个函数有什么问题的细节。我是用手机写的,请稍等片刻,我将添加一些示例,您可以如何编辑代码以使其正常工作。
  • 添加了一些代码,可能会为您指明您可能需要的方向。
  • 在我的任务中,我必须提供 dtcreated (date_created) 因为它会返回一个 varchar2 数据类型。我使用了第二个示例,它给了我工作日,但工作日以某种方式关闭。我不太确定为什么,但确实如此。我已经阅读了您的所有解释,并且我正在阅读的内容很有意义。
  • 他们过得怎么样?您认为它们以什么方式关闭?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-23
  • 1970-01-01
  • 2018-04-13
  • 1970-01-01
  • 1970-01-01
  • 2022-01-08
  • 1970-01-01
相关资源
最近更新 更多