我编写了一个包含2个子查询的查询。子查询会格式化结果字段名称和数据类型,因此它们是相同的。主要查询是直接的UNION。
两个子查询都从托管的Oracle服务器检索数据;我们无法控制数据库结构。两个子查询之一使用字符串数据类型包含DateTime。我在SELECT中使用以下代码将值转换为DateTime并添加2小时以调整时区:
TO_DATE(TCF.TRANS_DATE, 'MM-DD-YYYY HH24:MI:SS') + 2/24 AS TRANS_DT,
这将产生正确的值。
这是皱纹:WHERE子句中相同的TO_DATE产生错误ORA-01843:无效的月份。这是完整的WHERE子句:
WHERE TO_DATE(TCF.TRANS_DATE, 'MM-DD-YYYY HH24:MI:SS') + 2/24 >= {?START_DT}
一个明显的问题是,为什么上面的方法在SELECT中起作用,但在WHERE子句中抛出此错误?
该字段中的值采用TO_DATE语句中指定的格式。是不是我不希望SELECT语句产生错误,但是删除WHERE子句时没有错误。
由于参数{?START_DT}是Date数据类型,因此我尝试将TRUNC()添加到WHERE子句。我还用硬编码代替了使用该参数的有效日期。这些都不对错误有任何影响。
完成第二个子查询的WHERE子句对我来说就是完成此项目并继续进行的全部工作。我正在使用具有成熟可靠连接的Crystal Reports访问数据库。任何想法或建议都表示赞赏。
对于您的信息,这是整个查询:
SELECT DISTINCT TCF.TRIPCARD_UNIT_NO AS UNIT_NO,
TO_DATE(TCF.TRANS_DATE, 'MM-DD-YYYY HH24:MI:SS') AS TRANS_DT2,
TCF.ODOMETER AS METER
FROM MFIVE.VIEW_TRIPCARD_FAILED_TRANS TCF
WHERE TO_DATE(TCF.TRANS_DATE, 'MM-DD-YYYY HH24:MI:SS') >= TO_DATE('02-01-2019 00:00:00', 'MM-DD-YYYY HH24:MI:SS')
出于无奈,我从TRANS_DT字符串中解析了月,日和年的值。没有超出适当范围的值;特别是所有月份的值都在预期的1到12之间。
我在WHERE子句中针对上述串联的部分创建了一个新的TO_DATE语句。检查并仔细检查了格式...我得到了相同的错误。
在我看来,WHERE子句中不允许TO_DATE。还有其他人听说过此限制吗?是否可以在SQL中创建DateTime变量并将其传递给WHERE子句?
更新#3:
省略WHERE子句,我将查询的其余部分用作子查询,并对SELECT语句使用EXTRACT MONTH FROM TRANS_DT。此子查询的运行效果很好,并产生了从1到12的整数。这再次确认没有涉及格式错误的日期。
扩展了子查询的概念,我尝试通过以下语句应用WHERE子句:WHERE TRUNC(TCF2.TRANS_DT) >= TO_DATE('02/01/2019', 'MM/DD/YYYY')
产生了相同的错误!我闻到一个错误,但是如果我知道是什么,该死。
答案 0 :(得分:2)
我可以想到两个可能的原因:
首先,您正在运行查询,但仅查看结果的几行,而不是整个结果集。您看到的行日期没有问题。如果滚动到末尾,则会看到问题。
第二个原因是select
表达式是在 all 过滤之后运行的(至少在某些情况下)。错误的值可能会被其他过滤条件过滤掉。当表达式移到where
子句时,所有数据都可能通过此条件传递。
答案 1 :(得分:1)
当相等或匹配时,请检查数据类型:
WITH S_DT AS
(
SELECT TO_DATE(TO_CHAR(SYSDATE,'MM-DD-YYYY HH24:MI:SS'), 'MM-DD-YYYY HH24:MI:SS') START_DT FROM DUAL
),
TAB AS
(
SELECT TO_DATE(TO_CHAR(SYSDATE,'MM-DD-YYYY HH24:MI:SS'), 'MM-DD-YYYY HH24:MI:SS') + 2/24 AS TRANS_DT FROM DUAL
UNION ALL
SELECT TO_DATE(TO_CHAR(SYSDATE,'MM-DD-YYYY HH24:MI:SS'), 'MM-DD-YYYY HH24:MI:SS') - 2/24 FROM DUAL
UNION ALL
SELECT TO_DATE(TO_CHAR(SYSDATE,'MM-DD-YYYY'), 'MM-DD-YYYY') + 2/24 FROM DUAL
)
SELECT * FROM TAB,S_DT WHERE TAB.TRANS_DT >= S_DT.START_DT;
输出:
TRANS_DT START_DT
--------- ---------
2/22/2019 2:09:39 PM 2/22/2019 12:09:39 PM
或者,您也可以尝试使用此NEW_TIME
函数来进行time zone
的更改。
SELECT SYSDATE,
NEW_TIME(SYSDATE, 'GMT', 'EST')
FROM dual;
输出:
SYSDATE NEW_TIME(SYSDATE,'GMT','EST')
--------- -----------------------------
2/22/2019 12:10:10 PM 2/22/2019 7:10:10 AM