Oracle String Date to date 返回最近 7 天

Oracle String Date to date getting back last 7 days

我正在查询非常大的数据集。超过 9000 万行。我试图将数据限制在过去 7 天内,但我在使用 Oracle 语法时遇到了问题。数据库是 Oracle 11g

日期字段称为 START_UTC_DAY 它是一个字符串,看起来像 20200414

我试过了

 SELECT TO_DATE(START_UTC_DAY, 'YYYYMMDD')
FROM SOURCETABLE
WHERE START_UTC_DAY > SysDate - 7

我得到 ORA-01861 文字与格式字符串不匹配

请原谅我的无知,我的 SQL 是初级的,我正在边学边学。

SELECT TO_DATE(START_UTC_DAY, 'YYYYMMDD')
FROM SOURCETABLE
WHERE TO_DATE(START_UTC_DAY, 'YYYYMMDD') > SysDate - 7
WHERE 子句中的

TO_DATE() 将具有给定格式模型的字符串值转换为 DATE 类型,然后再将其与另一个 DATE 值进行比较,从而避免导致问题的隐式转换。查看评论以获得更好的变化。

此处的信息是避免隐式转换。

解释:

错误是由于 WHERE 子句中的隐式转换,即不同数据类型的两个值之间的比较。

2.2.8.2 Implicit Data Conversion

  • 将字符值与 DATE 值进行比较时,Oracle
    将字符数据转换为 DATE。

在转换过程中,字符 value/string 文字根据取决于以下设置的日期格式模型进行评估。

select name, value from v$parameter where name = 'nls_date_format';

在我的数据库中 returns,

NAME                 VALUE               
-------------------- --------------------
nls_date_format      DD-MON-YY 

可以在会话级别更改此设置,这将产生如下所示的各种结果。

这里有一些测试可以进一步解释使用 SQL 开发人员使用新会话的行为。

SQL> show parameter nls_date_format;
NAME            TYPE   VALUE     
--------------- ------ --------- 
nls_date_format string DD-MON-YY 


SQL> 
select str from 
(select '20200412' as str from dual)
where str <> sysdate;

...
Error report -
ORA-01861: literal does not match format string


SQL> 
alter session set nls_date_format = 'ddmmyyyy';

Session altered.

SQL> 
SQL> show parameter nls_date_format;
NAME            TYPE   VALUE    
--------------- ------ -------- 
nls_date_format string ddmmyyyy 


SQL> 
select str from 
(select '20200412' as str from dual)
where str <> sysdate;

...
Error report -
ORA-01843: not a valid month


SQL> 
alter session set nls_date_format = 'fxyyyy-mm-dd';

Session altered.

SQL> 
SQL> show parameter nls_date_format;
NAME            TYPE   VALUE        
--------------- ------ ------------ 
nls_date_format string fxyyyy-mm-dd 


SQL> 
select str from 
(select '20200412' as str from dual)
where str <> sysdate;

...
Error report -
ORA-01861: literal does not match format string


SQL> 
alter session set nls_date_format = 'yyyymmdd';

Session altered.

SQL> 
SQL> show parameter nls_date_format;
NAME            TYPE   VALUE    
--------------- ------ -------- 
nls_date_format string yyyymmdd 


SQL> 
select str from 
(select '20200412' as str from dual)
where str <> sysdate;

STR     
--------
20200412

如上所示,根据 nls_date_format 设置,相同的查询最终会产生不同的 "results"。

我想你可能想要 TO_CHAR() 而不是 TO_DATE():

SELECT TO_CHAR(START_UTC_DAY, 'YYYYMMDD')
FROM SOURCETABLE
WHERE START_UTC_DAY > SysDate - 7;

请注意 sysdate 有一个时间部分。因此,您可能需要:trunc(sysdate) - interval '7' day(我更喜欢显式 interval 语法)。

The date field is called START_UTC_DAY it is a string and looks like 20200414

当你说日期看起来像 20200414 并不意味着它是一个字符串,它只是意味着你的 locale-specific NLS settings 被设置为显示日期以那种格式。但它实际上并没有以任何格式存储。

I get the ORA-01861 Literal does not match format string

那是因为你在日期上使用TO_DATE,因此强制Oracle根据NLS依赖格式将DATE转换为字符串,然后再转换回使用您提到的格式的日期。这会导致 ORA-01861 Literal does not match format string 错误。

永远不要在日期列上使用 TO_DATE,使用 TO_CHAR 以您想要的格式显示它:

SELECT TO_CHAR(START_UTC_DAY, 'YYYYMMDD')
FROM SOURCETABLE
WHERE START_UTC_DAY > SYSDATE -7;

此外,请记住 DATE 也有最多秒的时间部分。如果您只想要没有时间的日期部分,则需要使用 TRUNC(SYSDATE).