无法更正 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 ENDVMP.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_DTNULL 时,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 中缺少关键字的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 错误:ORA-00905:缺少关键字

PL/SQL SELECT INTO 错误 (ORA-00905)

动态 Oracle 错误

甲骨文。使用 case 语句时缺少关键字。错误 00905

错误:ORA-00905:将表连接到选择查询时缺少关键字

缺少关键字ORA00905