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
我认为使函数 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"
为什么这个 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
我认为使函数 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"