在SQL中的Case语句中解码

时间:2011-09-16 16:53:21

标签: sql oracle

为什么这个查询没有意义?它给出了错误“缺少表达式”。

update wr_rpt_group a
set a.rpt_category_id = 
case
  when (select c.control_plan from grpmisc c where 
    c.grp = a.grp and c.sect = a.sect or a.sect in ('ALL','*'))
    then decode(c.control_plan, '01', '201', '02', '202', '03', '203', '93')
      else '93'
  end      
where a.rpt_category_id = '93';

谢谢!

4 个答案:

答案 0 :(得分:1)

表达式(您的查询)的值缺失,并且C在其范围之外使用。

按如下所示查看查询中的嵌入式注释:

UPDATE WR_RPT_GROUP A
set A.RPT_CATEGORY_ID = CASE
    WHEN ( -- scope of C starts from here
        SELECT
            C.CONTROL_PLAN
        FROM
            GRPMISC C
        WHERE
            C.GRP = A.GRP
            AND C.SECT = A.SECT
                OR A.SECT IN (
                'ALL',
                '*'
            )
    ) -- scope of C ends here
    -- you have just one side expression of the operator where is other side of operation? (query) = (something)
    THEN DECODE(C.CONTROL_PLAN, '01', '201', '02', '202', '03', '203', '93')
      else '93' END WHERE A.RPT_CATEGORY_ID = '93';

我认为您可以执行以下操作:

UPDATE WR_RPT_GROUP A
SET
    A.RPT_CATEGORY_ID = CASE (
        SELECT MAX(C.CONTROL_PLAN) --max is used to avoid multiple records and eventually to avoid an error
          FROM GRPMISC C
         WHERE C.GRP = A.GRP
           AND (C.SECT = A.SECT
            OR A.SECT IN ('ALL', '*')) -- combined OR conditions together using paranthesis
    )
        WHEN '01'   THEN '201'
        WHEN '02'   THEN '202'
        WHEN '03'   THEN '203'
        ELSE A.RPT_CATEGORY_ID END
WHERE A.RPT_CATEGORY_ID = '93';

干杯!

答案 1 :(得分:0)

这里的一个问题是您可能会从select语句中返回多个值。如果是这种情况,那么您的更新语句将不起作用,因为您无法将单个列更新为多个值。如果您知道情况并非如此,那么这应该有效:

update wr_rpt_group a
set a.rpt_category_id = select decode(c.control_plan, 
                                      '01', '201', 
                                      '02', '202', 
                                      '03', '203', 
                                      '93') 
                        from grpmisc c 
                        where c.grp = a.grp 
                        and c.sect = a.sect 
                        or a.sect in ('ALL','*'))
where a.rpt_category_id = '93'
and   exists (select 1
          from grpmisc c 
          where c.grp = a.grp 
          and c.sect = a.sect 
          or a.sect in ('ALL','*'))

在尝试对其运行更新之前,您需要第二部分以确保存在将rpt_category_id设置为的记录。如果您还想确保没有重复记录,可以将最后一部分更改为:

and   1 in (select count(1)
          from grpmisc c 
          where c.grp = a.grp 
          and c.sect = a.sect 
          or a.sect in ('ALL','*'))

答案 2 :(得分:0)

您收到错误的原因是您的案例表达式没有运算符。 Oracle不知道在case语句中如何处理该查询(我也不知道):您是否尝试测试是否存在?你在寻找具体的价值吗?

此外,在同一语句中同时使用casedecode是愚蠢和混乱(更不用说在这种情况下不必要了)。我想你想要的是这个:

UPDATE wr_rpt_group a
SET    a.rpt_category_id   =
          CASE (SELECT c.control_plan
                FROM   grpmisc c
                WHERE  c.grp = a.grp 
                  AND  c.sect = a.sect 
                   OR  a.sect IN ('ALL', '*'))
             WHEN '01' THEN '201'
             WHEN '02' THEN '202'
             WHEN '03' THEN '203'
             ELSE '93'
          END
WHERE  a.rpt_category_id = '93';

最后,我要非常小心地混合andor,而不是再加上一些括号。现在,我认为您的查询将被评估为c.grp_ = a.grp and (c.sect = a.sect or a.sect in ('ALL','*')),但我只是不确定。添加一些括号而不是依赖于对先例顺序的记忆总是更好。

答案 3 :(得分:0)

关于包围:AND的优先级高于OR,因此 给定的查询求值为

(c.grp_ = a.grp and c.sect = a.sect)
or
a.sect in ('ALL','*')

这是 - 在我看来 - 不是预期的。 至少,包围为

c.grp_ = a.grp
and
( c.sect = a.sect or a.sect in ('ALL','*'))

对我来说更有意义。

甚至更好:

c.grp_ = a.grp
and
a.sect in ('ALL','*',c.sect)