ORA-00905: 缺少关键字

Posted

技术标签:

【中文标题】ORA-00905: 缺少关键字【英文标题】:ORA-00905: missing keyword 【发布时间】:2015-02-09 10:05:09 【问题描述】:

我的表有这些列:

|blo|NotionalCurrency|Notional|Premiumcurrency|Basecurrency|Termcurrency|StructureName|Basemarketprice|Termmarketpriceprecent |Termmarketprice|

我想从这些中获取 blo、货币和价格。下面是我的 SQL:

   select blo.opt,
  case
  when opt.premiumcurrency is not null and opt.structurename is not null  then currency = opt.premiumcurrency
      case
      when opt.notionalcurrency = opt.basecurrency and opt.premiumcurrency = opt.termcurrency then price = opt.termmarketpricepercent / opt.notional
      else
          case
             when opt.premiumcurrency = opt.basecurrency then price = opt.basemarketprice /100
             else
             price = opt.termmarketpriceprecent /100
             end
       end
   when price = 0 then price = 0.000001
   end
FROM interface opt
WHERE opt.notionalcurrency = opt.basecurrency and opt.premiumcurrency = opt.termcurrency;

但我收到错误:ORA-00905: missing keyword

基本上应该使用下面的逻辑来获取/派生SQL来获取三列:Blo、货币和价格:

If notional currency = base currency and premium currency=term currency Then
               Price =term market price/notional
               currency = notional currency
Else
               If notional currency = premium currency then
                              Price= base market price /100
                              currency = termcurrency
               else
                              Price=term market price percent /100
                              currency = notional
               end if
end if
if price=0 then 
price=0.000001
end if

【问题讨论】:

blo.opt后面少了一个逗号 第二种情况跟在第一种情况之后,没有 else/case 条件。另外我认为您无缘无故有太多嵌套案例,请edit 并发布您的具体要求 以使现有答案无效的方式编辑您的问题似乎有点粗鲁。现在提出这个问题的人会认为 Bonesist 的答案是无关紧要或错误的,除非他们检查编辑历史记录。 @Alex。道歉。我不想提出另一个问题,这就是为什么。 【参考方案1】:

您在初始 case 语句中缺少 end。只需在when price = 0 then price = 0.000001后添加即可

【讨论】:

谢谢。我添加了它现在我得到ORA-00905: missing keyword @Sathya 已经为您提供了您现在收到缺少关键字错误的原因。他在他的cmets和答案中提出了一些优秀的观点! @ALL,我已经更新了获取所需 3 列所需的逻辑。提前致谢。【参考方案2】:

这里有很多问题。稍微分解一下:

  case
  when opt.premiumcurrency is not null
    and opt.structurename is not null

根据where 条件,opt.premiumcurrency 不能为空,因此检查不会添加任何内容。

  then currency = opt.premiumcurrency

您不能在此处设置值;正如 Arka 所示,您似乎希望这是一个在最终输出中标记为 currency 的表达式。

      case
      when opt.notionalcurrency = opt.basecurrency
        and opt.premiumcurrency = opt.termcurrency
      then price = opt.termmarketpricepercent / opt.notional

现在您要查找的是价格,而不是货币,所以这不是前面 case 子句的一部分;这意味着你现在应该有一个end as currency,。但是您也没有else 条件,这意味着如果opt.structurename 为空,您的货币表达式将为空;不清楚这是否是你想要的。

但是由于您的where 子句,这两个条件都必须为真,这使得整个case 变得多余。同样,您需要一个表达式别名,而不是尝试使用 = 设置值。

      else
          case
             when opt.premiumcurrency = opt.basecurrency
             then price = opt.basemarketprice /100
             else
             price = opt.termmarketpriceprecent /100
          end
       end

您在此处嵌套了一个案例,因此看起来您正在尝试直接转换 if/elsif/else 构造,而没有考虑 case 的语义实际上是如何工作的。不需要嵌套的 case/end,因为 when/end 可以是封闭 case 的一部分。但是如上所述,第一个when 条件必须始终为真,opt.premiumcurrency = opt.basecurrency 也必须始终为真,所以所有这些也是多余的。

   when price = 0 then price = 0.000001

这只是浮动在那里,所以这需要是一个外壳或解码,或者可能是一个least(),如果该值永远不会是负数。

因此,根据您显示的where 条件,这可以简化为:

select opt.blo,
  case
    when opt.structurename is not null then opt.premiumcurrency
  end as currency,
  case
    when opt.termmarketpricepercent = 0 then 0.000001
    else opt.termmarketpricepercent / opt.notional
  end as price
from interface opt
where opt.notionalcurrency = opt.basecurrency
and opt.premiumcurrency = opt.termcurrency;

如果where 子句是临时的,并且您需要更通用的查询,那么它仍然比您创建它更简单:

select opt.blo,
  case
    when opt.premiumcurrency is not null
      and opt.structurename is not null 
        then opt.premiumcurrency
    end as currency, -- still no 'else' so null if structurename is null
    decode (
      case
        when opt.notionalcurrency = opt.basecurrency
          and opt.premiumcurrency = opt.termcurrency
          then opt.termmarketpricepercent / opt.notional
        when opt.premiumcurrency = opt.basecurrency
          then opt.basemarketprice /100
        else opt.termmarketpricepercent /100
      end, 0, 0.000001) as price
from interface opt;

(我已将 blo.opt 交换为 opt.blo,正如 Sathya 所发现的那样,并且还修复了至少一个列引用中的错字...)

根据您的最新编辑,您希望根据相同的条件选择货币和价格,这在原始查询中并不明显。每种情况只能计算一个值,因此您需要在两个表达式中重复条件,一个是货币,一个是价格;然后如果价格为零,您仍然想更改价格。再次假设 where 是临时的:

select opt.blo,
  case
    when opt.notionalcurrency = opt.basecurrency
      and opt.premiumcurrency = opt.termcurrency
      then opt.notionalcurrency
    when opt.notionalcurrency = opt.premiumcurrency
      then opt.termcurrency
    else opt.notionalcurrency
  end as currency,
  decode (
    case
      when opt.notionalcurrency = opt.basecurrency
        and opt.premiumcurrency = opt.termcurrency
        then opt.termmarketpricepercent / opt.notional
      when opt.notionalcurrency = opt.premiumcurrency
        then opt.basemarketprice / 100
      else opt.termmarketpricepercent / 100
    end, 0, 0.000001) as price
from interface opt;

价格计算和以前一样,货币表达式已更改以匹配相同的逻辑。不过,您现在似乎丢失了structurename 支票。并且有一个基本假设,即所有货币值都不是空值,真的。

SQL Fiddle 有部分表,没有数据,只是为了显示查询不会出错。

【讨论】:

非常感谢。您的代码返回结果。由于要求似乎发生了一些变化,我会尽快回来。【参考方案3】:

试试这个:

SELECT opt.blo,
       CASE
         WHEN (opt.premiumcurrency IS NOT NULL
           AND opt.structurename IS NOT NULL) THEN
           currency = opt.premiumcurrency
       END,
       CASE
         WHEN (opt.notionalcurrency = opt.basecurrency
           AND opt.premiumcurrency = opt.termcurrency) THEN
           price = opt.termmarketpricepercent / opt.notional
         WHEN price = 0 THEN
           price = 0.000001
         WHEN opt.premiumcurrency = opt.basecurrency THEN
           price = opt.basemarketprice / 100
         ELSE
           price = opt.termmarketpriceprecent / 100
       END
  FROM interface opt
 WHERE opt.notionalcurrency = opt.basecurrency
   AND opt.premiumcurrency = opt.termcurrency;

【讨论】:

【参考方案4】:

我对这个查询有几点看法:

    据我了解,opt 是您的表的别名,要获取属性,您应该编写 opt.blo 而不是 blo.opt。 case 语句应包含 case 值,例如您使用 case 语句的列名

我已尝试修改代码。未编译,因此可能存在语法错误。看看就好。

  select opt.blo,
  case opt.currency
  when opt.premiumcurrency is not null and opt.structurename is not null
  then opt.premiumcurrency
  end as Currency,
  case opt.price
  when opt.notionalcurrency = opt.basecurrency and opt.premiumcurrency = opt.termcurrency then opt.termmarketpricepercent / opt.notional
  when opt.premiumcurrency = opt.basecurrency then opt.basemarketprice /100
  when price = 0 then price = 0.000001
  else
  opt.termmarketpriceprecent /100
  end as Price,
FROM interface opt
WHERE opt.notionalcurrency = opt.basecurrency and opt.premiumcurrency = opt.termcurrency;

【讨论】:

谢谢。我运行你的代码,但我仍然得到ORA-00905 如果您还尝试在when opt.premiumcurrency ... 条件中指定列,case opt.currency 是无效语法。 @Alex 我没有在 when 条件的任何地方使用列名 @ALL,我已经更新了获取所需 3 列所需的逻辑。提前致谢。 @ArkaBanerjee - 你在混音simple and searched case expression syntax。无论如何都没有一个简单的opt.currency 列,并且由于正在测试两件事,所以这不是一个简单的案例;它应该只是case when opt.premiumcurrency is not null ... 作为搜索案例?

以上是关于ORA-00905: 缺少关键字的主要内容,如果未能解决你的问题,请参考以下文章

ORA-00905 缺少关键字

ORA-00905: 缺少关键字 Hibernate 查询

ORA-00905: 缺少关键字(约束外键)

ORA-00905: TOAD 中缺少关键字

case 语句的“ORA-00905:缺少关键字”

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