Обновление с помощью row_number () в Oracle с несколькими строками - PullRequest
2 голосов
/ 09 сентября 2011

Вот сделка.У меня есть таблица с данными.Мне нужно заполнить поле с появлением строки на основе определенных полей.У меня может быть один ряд, у меня может быть 10. Мне нужно заполнить это число.Я использовал rownumber (), чтобы определить, что такое число.Однако обновление таблицы было проблематичным.Я пытался объединяет, что с таблицей, как, затем выберите, а затем обновление.Ничего не помогло.

Этот код:

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 Ответ

4 голосов
/ 10 сентября 2011

Проблема в том, что вам нужно работать со всем подзапросом как с одним набором, чтобы получить 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...