【问题标题】:How to use NVL in PL/SQL for Date columns?如何在 PL/SQL 中为日期列使用 NVL?
【发布时间】:2020-11-10 22:54:23
【问题描述】:

这是我在 Oracle 中的第一个 SP。

create or replace PROCEDURE SEARCH(R1 OUT SYS_REFCURSOR,
                                   UserID IN VARCHAR2,
                                   Name IN VARCHAR2,
                                   FromDate IN VARCHAR2,
                                   ToDate IN VARCHAR2
                                            )
                                             IS


BEGIN
           OPEN R1 FOR
           SELECT * FROM USER WHERE id = NVL( UserID, id )
           and ((LASTNAME =NVL(Name,LASTNAME)) OR( FIRSTNAME =NVL(Name, FIRSTNAME))) 
           and ( to_char(releaseddate, 'mm/dd/rrrr')  between FromDate and ToDate)
           order by RELEASEDDATE desc
           FETCH FIRST 100 ROWS ONLY;
END SEARCH;

在我的表中,我有 Id、FirstName、LastName 和 ReleasedDate 列。这些列不相互依赖。我使用 NVL 来处理 Table 列,但 RleasedDate 列取决于 FromDate 和 To date 输入参数。我尝试使用 NVL,但我遇到了问题。我正在接收 mm/dd/rrrr 格式的数据。有什么方法可以将 NVL 用于 Releaseddate 吗?

目前,我正在从已发布日期为空的表中接收所有数据,并且我正在尝试避免它。

提前感谢您的帮助。

and ( to_char(releaseddate, 'mm/dd/rrrr')  between FromDate and ToDate)

【问题讨论】:

  • 你想达到什么目的;如果过程参数之一为空,那么不要使用该值过滤相关的表列?如果 FromDate 有值但 ToDate 为空,反之亦然怎么办? (如果列值和参数都为空,则对名称使用 nvl 将不匹配,但这对您来说可能不是问题。)您还与 id 发生名称冲突 - 使参数名称与列名,例如带前缀;为什么从/到参数是字符串而不是日期?
  • @AlexPoole 所有列都是相互独立的。如果有一个非空输入参数,我至少会检索数据。如果从日期为空,那么我使用到日期值。如果 From date 和 To date 都为 null ,我不会用 releasedate 检索数据。
  • @AlexPoole 我更改了 Id 输入参数名称并更新了。
  • 除了您的其他问题:如果您的意思是您收到的参数 FromDate 和 ToDate 是 字符串 (无论格式),但列发布日期是 date 数据类型(应该是这样!)然后不要将发布日期转换为字符串。相反,使用 TO_DATE 函数将参数 FromDate 和 ToDate 转换为日期。 (更好:编写过程以接受这两个参数的 DATES;让调用者从字符串转换为日期,这不是您的过程为它们做的工作。)
  • 除了数据类型之间的转换...假设所有内容都已转换为日期。你想要像(releaseddate >= FromDate or FromDate is null) AND (releaseddate <= ToDate or ToDate is null) 这样的东西。不需要 NVL。

标签: oracle plsql


【解决方案1】:

我不会为此使用nvl,部分原因是它会排除为空的列值。我会明确地测试空参数;类似:

OPEN R1 FOR
    SELECT * FROM USER
    WHERE (UserID IS NULL OR id = UserID)
    AND (Name IS NULL OR LASTNAME = Name OR FIRSTNAME = Name)
    AND (FromDate IS NULL OR releaseddate >= TO_DATE(FromDate, 'dd/mm/rrrr'))
    AND (ToDate IS NULL OR releaseddate <= TO_DATE(ToDate, 'dd/mm/rrrr'))
    ORDER BY RELEASEDDATE DESC
    FETCH FIRST 100 ROWS ONLY;

这会将releasedate 列的值作为日期进行比较,而不是将其转换为字符串;而是将字符串参数转换为日期以匹配列数据类型,这样更有效。最好将过程参数声明为日期,并让调用者提供一个有效值。

【讨论】:

  • 感谢您的帮助。我将对此更改进行测试。
【解决方案2】:

不要试图将日期转换为字符串来比较它们——你只会得到意想不到的结果。而是将字符串转换为日期。

至于 RELEASEDATE 为 NULL - 我只是使用一个条件来测试这一点。假设您想包含 RELEASEDATE 为 NULL 的行,我建议:

create or replace PROCEDURE SEARCH(R1       OUT SYS_REFCURSOR,
                                   UserID   IN  VARCHAR2,
                                   Name     IN  VARCHAR2,
                                   FromDate IN  VARCHAR2,
                                   ToDate   IN  VARCHAR2)
IS
BEGIN
  OPEN R1 FOR
    SELECT *
      FROM USER
      WHERE id = NVL( UserID, id ) and
            ( LASTNAME  = NVL(Name, LASTNAME) OR
              FIRSTNAME = NVL(Name, FIRSTNAME) ) and
            ( REALEASEDDATE IS NULL OR
              REALEASEDDATE between TO_DATE(FromDate, 'mm/dd/rrrr')
                                and TO_DATE(ToDate, 'mm/dd/rrrr') )
           order by REALEASEDDATE desc
           FETCH FIRST 100 ROWS ONLY;
END SEARCH;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-27
    • 2017-04-30
    • 1970-01-01
    • 2010-11-02
    • 2018-09-23
    • 1970-01-01
    相关资源
    最近更新 更多