无法更正 Oracle 错误 ORA-00905 SQL 中缺少关键字
Posted
技术标签:
【中文标题】无法更正 Oracle 错误 ORA-00905 SQL 中缺少关键字【英文标题】:Unable to Correct Oracle Error ORA-00905 Missing Keyword in SQL 【发布时间】:2019-01-08 15:24:39 【问题描述】:我一直在研究这个简单的小sn-p 代码一天,但找不到导致错误的问题。正如标题所述,我在尝试执行以下代码时收到错误ORA-00905 Missing Keyword
:
SELECT DISTINCT DM.DESCRIPTION AS "AGENCY",
DM.DEPT_NO AS "DEPT NO",
CASE
WHEN VMP.RESERVE_DT IS NULL THEN
NULL
ELSE
VMP.RESERVE_DT
END AS "RESV_DT",
CASE
WHEN VMP.EST_PICKUP_DT IS NULL THEN
NULL
ELSE
VMP.EST_PICKUP_DT
END AS "EST_PKUP_DT",
CASE
WHEN VMP.EST_RETURN_DT IS NULL THEN
NULL
ELSE
VMP.EST_RETURN_DT
END AS "EST_RETN_DT",
VMP.EMP_NAME AS "EMPL_NAME",
VMP.UNIT_NO AS "UNIT_NUMBER",
VMP.RENTAL_CLASS_DESCRIPTION AS "RENT_CLS",
VMP.MP_TICKET_NO AS "MP_TKT_NO"
FROM DEPT_MAIN DM
INNER JOIN VIEW_MPOOL VMP ON VMP.DEPT_ID = DM.DEPT_ID
WHERE CASE
WHEN VMP.EST_PICKUP_DT IS NULL THEN
NULL
ELSE
TRUNC(VMP.EST_PICKUP_DT) = TRUNC(SYSDATE)
END
GROUP BY DM.DESCRIPTION,
DM.DEPT_NO,
CASE
WHEN VMP.RESERVE_DT IS NULL THEN
NULL
ELSE
VMP.RESERVE_DT
END,
CASE
WHEN VMP.EST_PICKUP_DT IS NULL THEN
NULL
ELSE
VMP.EST_PICKUP_DT
END,
CASE
WHEN VMP.EST_RETURN_DT IS NULL THEN
NULL
ELSE
VMP.EST_RETURN_DT
END,
VMP.EMP_NAME,
VMP.UNIT_NO,
VMP.RENTAL_CLASS_DESCRIPTION,
VMP.MP_TICKET_NO
ORDER BY CASE
WHEN VMP.EST_PICKUP_DT IS NULL THEN
NULL
ELSE
VMP.EST_PICKUP_DT
END ASC
此代码的基础是通过一个临时报告程序生成的,并且最初是完全合格的。我去掉了无关的引号并分配了表别名来清理它。虽然我希望这些努力能帮助我找到问题,但我找不到原因。感谢您的考虑。
【问题讨论】:
你很少在 GROUP BY 时不需要做 SELECT DISTINCT。 添加一些示例表数据和预期结果 - 全部作为格式化文本,而不是图像。先看看***.com/help/mcve。 你的CASE表达式没用:CASE WHEN VMP.RESERVE_DT IS NULL THEN NULL ELSE VMP.RESERVE_DT END
和VMP.RESERVE_DT
一样。
【参考方案1】:
尝试替换这个:
WHERE
CASE
WHEN VMP.EST_PICKUP_DT IS NULL THEN NULL
ELSE TRUNC(VMP.EST_PICKUP_DT) = TRUNC(SYSDATE)
END
与:
WHERE
CASE
WHEN VMP.EST_PICKUP_DT IS NULL THEN NULL
ELSE TRUNC(VMP.EST_PICKUP_DT)
END
= TRUNC(SYSDATE)
请注意,整个表达式(以及查询中的其他类似表达式)可以简化为:
WHERE
TRUNC(VMP.EST_PICKUP_DT) = TRUNC(SYSDATE)
当VMP.EST_PICKUP_DT
为NULL
时,TRUNC
将返回NULL
,这将不等于TRUNC(SYSDATE)
。
【讨论】:
@EzLo 您的回答与 GMB 并驾齐驱,但他首先出现,所以我给了它解决方案。你的答案在功能上是相同的,所以我确实给了两个赞成票。感谢你们两位的快速响应。【参考方案2】:这里:
WHERE
CASE
WHEN VMP.EST_PICKUP_DT IS NULL
THEN NULL
ELSE TRUNC(VMP.EST_PICKUP_DT) = TRUNC(SYSDATE)
END
END
是在比较之后,并且没有将大小写与值进行比较。
像这样切换:
WHERE
CASE
WHEN VMP.EST_PICKUP_DT IS NULL
THEN NULL
ELSE TRUNC(VMP.EST_PICKUP_DT)
END = TRUNC(SYSDATE)
正如马所说,可以简化为
WHERE TRUNC(VMP.EST_PICKUP_DT) = TRUNC(SYSDATE)
因为VMP.EST_PICKUP_DT
上的NULL
值永远不会匹配TRUNC(SYSDATE)
。
【讨论】:
可以简化为where TRUNC(VMP.EST_PICKUP_DT) = TRUNC(SYSDATE)
@a_horse_with_no_name 正确,我正忙于检查语法而不是语义。【参考方案3】:
找不到导致错误的问题
虽然我认为@EzLo 和@a_horse_with_no_name 在这种情况下可能已经发现错误,但我可以提出一个通用 程序来调试此类查询。
第 1 步:调试 JOIN- 和 WHERE- 谓词
注释 SELECT 语句中的所有内容,只保留 JOIN,用 *
或常量表达式替换字段。
例如
SELECT 1
-- DISTINCT DM.DESCRIPTION AS "AGENCY",
-- DM.DEPT_NO AS "DEPT NO",
-- CASE
-- ....
-- VMP.RENTAL_CLASS_DESCRIPTION AS "RENT_CLS",
-- VMP.MP_TICKET_NO AS "MP_TKT_NO"
FROM DEPT_MAIN DM
INNER JOIN VIEW_MPOOL VMP ON VMP.DEPT_ID = DM.DEPT_ID
WHERE CASE
WHEN VMP.EST_PICKUP_DT IS NULL THEN
NULL
ELSE
TRUNC(VMP.EST_PICKUP_DT) = TRUNC(SYSDATE)
END
-- GROUP BY DM.DESCRIPTION,
-- ....
-- ORDER BY ..
如果有多个复杂谓词 - 一次取消一个谓词的注释。
第 2 步:调试您的 GROUP BY 和 HAVING
取消注释 GROUP BY 部分并编辑查询的字段部分。 如果您有复杂的 groupby - 一次取消一个字段的注释。 从简单到复杂
SELECT
DM.DESCRIPTION
,DM.DEPT_NO
-- ...
FROM DEPT_MAIN DM
INNER JOIN VIEW_MPOOL VMP ON VMP.DEPT_ID = DM.DEPT_ID
WHERE CASE
WHEN VMP.EST_PICKUP_DT IS NULL THEN
NULL
ELSE
TRUNC(VMP.EST_PICKUP_DT) = TRUNC(SYSDATE)
END
GROUP BY DM.DESCRIPTION
,DM.DEPT_NO
将您的 GROUP BY 复制粘贴到 SELECT 字段部分。
第 3 步:调试聚合、字段转换和重命名
现在您有了正确的 SELECT 查询,但可能不是您想要的形状。
第 4 步:调试 ORDER BYs
你有正确的形状,在最后一步你需要按你的数据排序。
如果您有不错的编辑器/IDE,即使在复杂查询(甚至是 RDBMS 引擎错误)的情况下,您也可以在 5-10 分钟内找到错误源
附言
最好记下您使用的是哪个版本的 RDBMS。
【讨论】:
我使用了类似的过程,并且在发布之前解决了其他错误。我查看了 CASE END 语句并没有发现问题。谢谢你的建议!以上是关于无法更正 Oracle 错误 ORA-00905 SQL 中缺少关键字的主要内容,如果未能解决你的问题,请参考以下文章