使用Oracle中的row_number()更新多行

时间:2011-09-09 15:21:05

标签: oracle

这是合约。我有一张数据表。我需要根据某些字段填充行出现的字段。我可能有一排,我可能有10排。我需要填充这个数字。我一直在使用rownumber()来确定数字是多少。但是更新表格一直存在问题。我已经尝试了连接,使用tablename as,然后选择,然后更新。没有任何效果。

此代码:

update Rptdata
SET c98 = (SELECT R from 
                (select rs1.c1, rs1.c5,rs1.c3, 
                row_number() over(partition by rs1.c1,0, rs1.c5,rs1.c3 order by rs1.c1,rs1.c5,rs1.c3 desc) as R
                from Rptdata rs1
                where rs1.c1 = c1
                and   rs1.c5 = c5
                and   rs1.c3 = c3
         --       and   rs1.c6 = c6
         --       and   rs1.c7 = c7
         --       and   rs1.c8 = c8
         --       and   rs1.c9 = c9
                and   rs1.program_name = 'INTERNAL'
                AND   rs1.program_id=030911 
                AND (rs1.c6  IS NULL
                or rs1.c8  IS NULL
                or rs1.c9  IS NULL)
                and rs1.c28 IS NULL 
               )
          )  
WHERE program_name = 'INTERNAL'
AND program_id=030911
AND (c6  IS NULL
or c8  IS NULL
or c9  IS NULL)
and c28 IS NULL  

生成错误ORA-01427:单行子查询返回多行。我认为这就是我想要的。我取消评论 - 而rs1.c6 = c6 它告诉我我更新了187行(这是正确的)。我提交然后在那187行上运行一个选择,而c98中没有任何内容。

1 个答案:

答案 0 :(得分:4)

问题在于您需要将整个子查询作为一个单独的集处理,以便row_number为您提供所需的结果,但您还需要将该集合减少为单个记录为了更新每一行。虽然使用update可以实现这一点,但在这种情况下使用merge会更直接(假设您使用的是10g):

MERGE INTO rptdata rp
USING      (SELECT ROW_NUMBER() OVER (PARTITION BY rs1.c1, 0, rs1.c5, rs1.c3 
                                      ORDER BY rs1.c1, rs1.c5, rs1.c3 DESC) AS r
            FROM   rptdata rs1
            WHERE  rs1.program_name = 'INTERNAL'
               AND rs1.program_id = 030911
               AND (rs1.c6 IS NULL OR rs1.c8 IS NULL OR rs1.c9 IS NULL)
               AND rs1.c28 IS NULL) rs
ON         (rs.c1 = rp.c1 AND rs.c5 = rp.c5 AND rs.c3 = rp.c3)
WHEN MATCHED THEN
   UPDATE SET
      c98   = rs.r
      WHERE      program_name = 'INTERNAL'
             AND program_id = 030911
             AND (c6 IS NULL OR c8 IS NULL OR c9 IS NULL)
             AND c28 IS NULL

顺便提一下,您提供的查询并不遥远。如上所述,您需要使用row_number获取整个集合,然后筛选每个要更新的行所需的单个记录。为此,您需要将连接条件移动到外部查询:

UPDATE rptdata
SET    c98   =
          (SELECT r
           FROM   (SELECT rs1.c1,
                          rs1.c5,
                          rs1.c3,
                          ROW_NUMBER() OVER (PARTITION BY rs1.c1, 0, rs1.c5, rs1.c3 
                                             ORDER BY rs1.c1, rs1.c5, rs1.c3 DESC)
                             AS r
                   FROM   rptdata rs1
                   WHERE  rs1.program_name = 'INTERNAL'
                      AND rs1.program_id = 030911
                      AND (rs1.c6 IS NULL OR rs1.c8 IS NULL OR rs1.c9 IS NULL)
                      AND rs1.c28 IS NULL)
           WHERE  rs1.c1 = c1 AND rs1.c5 = c5 AND rs1.c3 = c3)
WHERE  program_name = 'INTERNAL' 
   AND program_id = 030911 
   AND (c6 IS NULL OR c8 IS NULL OR c9 IS NULL) 
   AND c28 IS NULL