案例只是给我相同的日期:(

时间:2017-11-22 14:50:04

标签: sql oracle case

此CASE仅显示同一日期'01 / 01/2999',我需要在日期少于'01 / 01/1950'时才能获得此日期'01 / 01/2999'。

如果有人可以帮助我,我会感激不尽

to_char((
  CASE
    WHEN to_date(RM.REME_FECHA_ENTREGA,'DD/MM/YYYY') <= to_date('01/01/1950','DD/MM/YYYY') 
  THEN
    to_date('01/01/2999','DD/MM/YYYY')
  ELSE
    to_date(RM.REME_FECHA_ENTREGA,'DD/MM/YYYY')
  END) ,'DD/MM/YYYY')
  as FechaEntregaRemesa

2 个答案:

答案 0 :(得分:3)

这是因为您正在进行隐式日期转换,而您的NLS_DATE_FORMAT有两位数的年份,例如'DD/MM/YY'或者这个:

alter session set nls_date_format = 'DD-Mon-RR';

-- CTE to generate two dummy values
with RM (REME_FECHA_ENTREGA) as (
  select date '1950-01-01' from dual
  union all select date '1950-01-02' from dual
)
-- your query plus the original date value
select to_char(RM.REME_FECHA_ENTREGA, 'SYYYY-MM-DD') as REME_FECHA_ENTREG,
to_char((
  CASE
    WHEN to_date(RM.REME_FECHA_ENTREGA,'DD/MM/YYYY') <= to_date('01/01/1950','DD/MM/YYYY') 
  THEN
    to_date('01/01/2999','DD/MM/YYYY')
  ELSE
    to_date(RM.REME_FECHA_ENTREGA,'DD/MM/YYYY')
  END) ,'DD/MM/YYYY')
  as FechaEntregaRemesa
from rm;

REME_FECHA_ FECHAENTRE
----------- ----------
 1950-01-01 01/01/2999
 1950-01-02 01/01/2999

使用4位数格式,它可以按预期工作:

alter session set nls_date_format = 'DD/MM/YYYY';

...

REME_FECHA_ FECHAENTRE
----------- ----------
 1950-01-01 01/01/2099
 1950-01-02 02/01/1950

当你这样做时

to_date(RM.REME_FECHA_ENTREGA,'DD/MM/YYYY')

你真的真的在做:

to_date(to_char(RM.REME_FECHA_ENTREGA, '<NLS_DATE_FORMAT>'),'DD/MM/YYYY')

这就是为什么你看到2位数年份模型的问题。隐式to_char(RM.REME_FECHA_ENTREGA, 'DD-MON-RR')将提供类似'01-JAN-50'的字符串。当您将该字符串传递回to_date()并使用YYYY格式模型时,它被解释为0050年,所以它总是在1950年之前。

"Oracle Database converts strings to dates with some flexibility",这并不总是有用......在这里,我们并没有抱怨你为4位数模型提供了两位数字,或者(在我的例子中)你提供了#&# 39; ve通过了一个月的缩写而不是一个月的数字。 (您可以使用FM / FX修改器更改行为,但默认情况下它是灵活的。)

您可能会像我在此演示中使用alter session一样,但不应该依赖于NLS设置,因为您通常无法控制其他用户和其他用户。设置将是。 (我怀疑你没有意识到你在这个查询中,但它仍然需要注意。)当你必须将日期转换为字符串时,总是使用显式转换和完整格式模型,反之亦然。

但您根本不需要转换现有的日期值。这是一个约会,所以不要管它。您还可以将日期文字用于固定值,以避免任何歧义,并减少输入:

to_char(
  CASE
    WHEN RM.REME_FECHA_ENTREGA <= date '1950-01-01'
  THEN
    date '2099-01-01'
  ELSE
    RM.REME_FECHA_ENTREGA
  END,'DD/MM/YYYY')
  as FechaEntregaRemesa

...

REME_FECHA_ FECHAENTRE
----------- ----------
 1950-01-01 01/01/2099
 1950-01-02 02/01/1950

甚至(修改@ expenguin的建议)仅在必要时使用日期:

  CASE
    WHEN RM.REME_FECHA_ENTREGA <= date '1950-01-01'
  THEN
    '01/01/2099'
  ELSE
    TO_CHAR(RM.REME_FECHA_ENTREGA, 'DD/MM/YYYY')
  END as FechaEntregaRemesa

答案 1 :(得分:2)

编辑:如果您的数据已经存储为文本,看起来您甚至不需要to_char,并且您不需要它进行比较。转换为日期是比较字符串文字时唯一需要的。

所以我们采用OP的代码:

to_char((
  CASE
    WHEN to_date(RM.REME_FECHA_ENTREGA,'DD/MM/YYYY') <= to_date('01/01/1950','DD/MM/YYYY') 
  THEN
    to_date('01/01/2999','DD/MM/YYYY')
  ELSE
    to_date(RM.REME_FECHA_ENTREGA,'DD/MM/YYYY')
  END) ,'DD/MM/YYYY')
  as FechaEntregaRemesa

并在下方更改

如果REME_FECHA_ENTREGA是日期:

  CASE
    WHEN RM.REME_FECHA_ENTREGA <= date '1950-01-01'
  THEN
    '01/01/2099'
  ELSE
    to_char(RM.REME_FECHA_ENTREGA, 'MM/DD/YYYY')
  END as FechaEntregaRemesa

如果REME_FECHA_ENTREGA是一个字符串:

  CASE
    WHEN to_date(RM.REME_FECHA_ENTREGA, 'DD/MM/YYYY') <= date '01/01/1950'
  THEN
    '01/01/2999'
  ELSE
    RM.REME_FECHA_ENTREGA
  END as FechaEntregaRemesa