SQL 错误,代码=1843,消息=ORA-01843:不是有效月份 (50,380)。完全使用 TO_CHAR(TO_DATE()) 函数匹配格式

问题描述 投票:0回答:3

目标是从

YYYY
中提取
A.SCC_ROW_ADD_DTTM
,格式为DateTm

使用 peoplesoft 查询管理器,添加希望从 DateTm 字段中提取年份的表达式。

在 DateTm 字段上运行查询以下列格式显示日期:03/19/2017 12:00:23PM

所以我尝试了

TO_CHAR(TO_DATE(A.SCC_ROW_ADD_DTTM, 'MM/DD/YYYY HH:MI:SSPM'), 'YYYY')

但是一直报错not a valid month (50,380), but every date in the list in the months starts with months in the format of XX (01-12).完整代码如下

SELECT A.ITEM_TYPE, B.DESCR, SUM( A.ITEM_AMT- A.APPLIED_AMT), TO_CHAR(TO_DATE(TO_CHAR(CAST((A.SCC_ROW_ADD_DTTM) AS TIMESTAMP),'YYYY-MM-DD-HH24.MI.SS.FF'), 'MM/DD/YYYY HH:MI:SSPM'), 'YYYY'), TO_CHAR(CAST((A.SCC_ROW_ADD_DTTM) AS TIMESTAMP),'YYYY-MM-DD-HH24.MI.SS.FF')
  FROM PS_ITEM_SF A, PS_ITEM_TYPE_TBL B
  WHERE ( B.ITEM_TYPE = A.ITEM_TYPE
    AND ( A.ITEM_TYPE IN ('600000050010','600000050020','600000050030')
     AND B.EFFDT =
        (SELECT MAX(B_ED.EFFDT) FROM PS_ITEM_TYPE_TBL B_ED
        WHERE B.SETID = B_ED.SETID
          AND B.ITEM_TYPE = B_ED.ITEM_TYPE
          AND B_ED.EFFDT <= SYSDATE) ))
  GROUP BY  A.ITEM_TYPE,  B.DESCR,  TO_CHAR(TO_DATE( TO_CHAR(CAST((A.SCC_ROW_ADD_DTTM) AS TIMESTAMP),'YYYY-MM-DD-HH24.MI.SS.FF'), 'MM/DD/YYYY HH:MI:SSPM'), 'YYYY'),  A.SCC_ROW_ADD_DTTM
  HAVING ( SUM( A.ITEM_AMT- A.APPLIED_AMT) > 0)
  ORDER BY 1

我试过更改日期格式,但从任何内容更改时都会出现更严重的错误,但现在的表达式是什么,我只是不知道为什么它说月份不正确。

编辑:我现在注意到 peoplesoft 查询管理器自动将字段转换为时间戳,没有办法阻止这种情况,所以我认为没有办法解决这个问题。

sql oracle peoplesoft peoplesoft-query
3个回答
1
投票

错误、名称和描述方式表明

SCC_ROW_ADD_DTTM
是 DATE 列,而不是 VARCHAR2 - 这很好,因为您不应该将日期存储为字符串。

因为它已经是一个日期,所以您应该 not

TO_DATE(SCC_ROW_ADD_DTTM, ...)
或您现在拥有的其他一些转换。日期以内部格式存储,并通过明确的
TO_CHAR()
或由您的客户自动转换为人类可读的内容。看起来您的客户端在您查询表时将值显示为 MM/DD/YYYY HI:MI:SSPM。这并不意味着该列本身具有该(或任何)格式。

您需要删除大部分转换:

SELECT
  A.ITEM_TYPE,
  B.DESCR,
  SUM(A.ITEM_AMT - A.APPLIED_AMT),
  TO_CHAR(A.SCC_ROW_ADD_DTTM, 'YYYY'),
  TO_CHAR(CAST(A.SCC_ROW_ADD_DTTM AS TIMESTAMP), 'YYYY-MM-DD-HH24.MI.SS.FF')
FROM PS_ITEM_SF A
JOIN PS_ITEM_TYPE_TBL B
ON B.ITEM_TYPE = A.ITEM_TYPE
WHERE A.ITEM_TYPE IN ('600000050010', '600000050020', '600000050030')
AND B.EFFDT = (
  SELECT MAX(B_ED.EFFDT)
  FROM PS_ITEM_TYPE_TBL B_ED
  WHERE B.SETID = B_ED.SETID
  AND B.ITEM_TYPE = B_ED.ITEM_TYPE
  AND B_ED.EFFDT <= SYSDATE
)
GROUP BY A.ITEM_TYPE, B.DESCR, A.SCC_ROW_ADD_DTTM
HAVING SUM(A.ITEM_AMT - A.APPLIED_AMT) > 0
ORDER BY 1

小提琴

我还切换到现代连接语法,简化了 group by 子句等

如果您的专栏实际上是 TIMESTAMP 那么以上所有内容都适用,只需删除

CAST()
调用(fiddle)。即使使用 DATE,您也可以删除它并将固定的
.000000
或只是
.0
添加到格式模型中以进行显示。

你也可以做

EXTRACT(YEAR FROM ...)
而不是
TO_CHAR(..., 'YYYY')
,这会将结果作为数字而不是字符串 - 取决于你想要的。


0
投票

Peoplesoft 将自动执行 TO_CHAR,因此您需要将其转换回日期,然后再次转换为 TO_CHAR(...,'YYYY'),这通常是我使用表达式执行此操作的方式。


0
投票

PS/Query 很奇怪,但我想出了怎么做。创建一个字符类型的表达式并使用 substr(A.SCC_ROW_ADD_DTTM,1,4) 获取年份的前 4 个字符。

我用这样一个简单的 PSOPRDEFN 查询来完成它:

生成此查询:

SELECT A.OPRID, TO_CHAR(A.LASTSIGNONDTTM,'YYYY-MM-DD-HH24.MI.SS."000000"'), 
substr( TO_CHAR(A.LASTUPDDTTM,'YYYY-MM-DD-HH24.MI.SS."000000"'),1,4)
FROM PSOPRDEFN A

这是当年的产出:

这里的关键是PS/Query中的表达式文本“substr(A.LASTUPDDTTM,1,4)”被翻译成substr( TO_CHAR(A.LASTUPDDTTM,'YYYY-MM-DD-HH24.MI.SS." 000000"'),1,4) 对于 Oracle。

© www.soinside.com 2019 - 2024. All rights reserved.