NEXT_DAY 函数在 SQL 和 PL/SQL 中的工作方式不同?

NEXT_DAY function works differently in SQL vs. PL/SQL?

为什么这个 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

我不想将第二个参数硬编码为一天的英文名称 ex。 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;

这是我的开发环境:

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.

如果您查看 SQL 版本 NEXT_DAY 的文档,您会发现没有记录传递数字来表示星期几。无论出于何种原因,它都可以工作,但如果您依赖它工作,您就冒着未来 Oracle 将更改实现以符合该功能的规定规范的风险。 (风险很小,因为 Oracle 并不疯狂。)

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

PL/SQL 实现仅适用于记录的规范 - 它不接受表示星期几的数字输入。

我想这是一个间接的回答。我相信你问错了问题。问题不应该是"why doesn't this work in PL/SQL";相反,鉴于文档,问题应该是 "why does it work in Oracle SQL"。只有 Oracle 可以回答这个问题。

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

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

我认为使函数 NEXT_DAY 独立于当前会话 NLS_DATE_LANGUAGE 的唯一方法是使用 ISO 周,其中一周的第一天始终是星期一:

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

TRUNC(SYSDATE, 'IW')+5 表示 "Next Saturday"