【问题标题】:NEXT_DAY function works differently in SQL vs. PL/SQL?NEXT_DAY 函数在 SQL 和 PL/SQL 中的工作方式不同?
【发布时间】:2017-08-23 14:25:52
【问题描述】:

为什么这个 SQL 查询有效:

SELECT NEXT_DAY(SYSDATE, 7)
FROM DUAL;
NEXT_DAY(SYSDATE,7)
-------------------
01-APR-17          
1 row selected.

...但是这个匿名的 PL/SQL 块不起作用?

DECLARE
  dteExpires DATE;
BEGIN
  dteExpires := NEXT_DAY(SYSDATE, 7);
END;
Error at line 1
ORA-01846: not a valid day of the week
ORA-06512: at line 4

我不想将第二个参数硬编码为前一天的英文名称。 NEXT_DAY(SYSDATE, 'SATURDAY')NEXT_DAY(SYSDATE, 'SUNDAY') 等。

目前,我将使用以下解决方法,但我真的很想知道为什么NEXT_DAY() 在 PL/SQL 中的行为与在 SQL 中的行为不同。

DECLARE
  dteExpires DATE;
BEGIN
  -- 2017-01-01 = SUNDAY
  dteExpires := NEXT_DAY(SYSDATE, TO_CHAR(TO_DATE('2017-01-01', 'YYYY-MM-DD'), 'DAY'));
END;

这是我的 DEV 环境:

SELECT *
FROM v$version;
BANNER                                                                

-------------------------------------------------------------------------------- 
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
PL/SQL Release 12.1.0.2.0 - Production                 
CORE  12.1.0.2.0  Production                                            
TNS for 64-bit Windows: Version 12.1.0.2.0 - Production               
NLSRTL Version 12.1.0.2.0 - Production                                

5 rows selected.

【问题讨论】:

  • 11g XE 中的行为相同。

标签: sql oracle date plsql oracle12c


【解决方案1】:

如果您查看 NEXT_DAY 的 SQL 版本的文档,您会发现传递一个数字来表示一周中的某一天是没有文档记录的。无论出于何种原因,它都可以工作,但如果您依赖它工作,那么您将承担未来 Oracle 将更改实现以符合该函数的规定规范的风险。 (风险很小,因为 Oracle 并不疯狂。)

https://docs.oracle.com/database/121/SQLRF/functions118.htm#SQLRF00672

PL/SQL 实现仅适用于文档化规范 - 它不接受数字输入来表示一周中的某一天。

我想这是一个间接的答案。我相信你问错了问题。问题不应该是“为什么这在 PL/SQL 中不起作用”;相反,鉴于文档,问题应该是“为什么它在 Oracle SQL 中工作”。只有甲骨文可以回答这个问题。

您可能会发现 OTN 上的此讨论很有用:https://community.oracle.com/thread/4023654

也许这也是:https://community.oracle.com/ideas/17257?tab=comment

【讨论】:

  • 是的,我想我是在反问这个问题,或者说真的,我应该问:“为什么没有办法正确地做到这一点?!?”我希望有一天 Oracle 添加一个可选的 NLS_DATE_LANGUAGE 参数。
【解决方案2】:

我认为使函数 NEXT_DAY 独立于当前会话 NLS_DATE_LANGUAGE 的唯一方法是解决 ISO 周的问题,其中一周的第一天总是星期一:

SELECT NEXT_DAY(SYSDATE, TO_CHAR(TRUNC(SYSDATE, 'IW')+5, 'Day')) 
from dual;

TRUNC(SYSDATE, 'IW')+5 表示“下周六”

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-27
    • 2015-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-15
    • 1970-01-01
    相关资源
    最近更新 更多