Может кто-нибудь помочь мне с моим сценарием pl / sql для обновления / слияния в базе данных - PullRequest
3 голосов
/ 02 февраля 2012

Я сделал курсор для объединения / обновления записей в базе данных

Мне было интересно, если это правильно или у кого-нибудь есть какие-либо предложения по улучшению запроса.

Ответы [ 3 ]

7 голосов
/ 02 февраля 2012

Предполагая, что код выполняет функционально то, что вы хотите ...

1) Удалить обработчик исключений. Нет смысла отлавливать неизвестное исключение, которое вы не сможете обработать, если не будете делать что-то вроде регистрации и повторного выброса. Перехват исключения только для вызова dbms_output не только скрывает детали исключения и трассировку стека, необходимые для отладки исключения, но и может полностью скрыть исключение, если вызывающий объект не читает из буфера dbms_output записи в .

2) Фиксация в цикле, как правило, плохая идея. Самое главное, что произойдет, если ваш сеанс умирает в середине? У вас будет частично зафиксированное обновление без возможности возобновить операцию, когда вы перезапустите код позже. Вам нужно будет обновить все строки, которые вы ранее обновили, и чьи обновления вы зафиксировали, что может оказать влияние на последующие. А фиксация в цикле замедляет ваш код без реальной причины.

3) Если все, что вы пытаетесь сделать, это обновить таблицу, то наиболее эффективным подходом было бы написать один оператор UPDATE, который обновляет все строки одновременно, а не перебирать курсор и выполнять много одиночных операций. обновления Могут быть и другие причины отдать предпочтение курсору (например, это может облегчить понимание кода другими разработчиками), но с точки зрения производительности, если вы можете сделать это в SQL, SQL будет наиболее эффективным подходом.

4 голосов
/ 02 февраля 2012

1) Вы заменяете значимую ошибку бессмысленной. Кроме того, если у вас нет set output on, ошибка будет полностью пропущена. Лучше всего просто удалить блок исключения. Если вы не можете этого сделать, вы должны сбросить как минимум SQLERRM и, вероятно, DBMS_UTILITY.FORMAT_ERROR_BACKTRACE до DBMS_OUTPUT. Чтобы правильно отлавливать и записывать ошибки, вам необходимо передать подробности исключения в отдельную процедуру, которая будет использовать автономную транзакцию для записи этих сведений в таблицу. Тем не менее, даже в этом случае лучше повторно вызвать ошибку после ее записи.

2) В большинстве случаев фиксация каждой X-записи является плохой практикой. Если все эти записи обновляются вместе, то они должны быть частью одной транзакции.

3) Вы можете сделать это в одном выражении, используя UPDATE или MERGE. Обычно это предпочтительнее, так как избегает дополнительных переключений контекста. Лично мне нравится MERGE в этом сценарии:

MERGE INTO item_loc il
USING      (SELECT item,
                   loc,
                   loc_type,
                   source_method,
                   primary_supp,
                   source_wh
            FROM   (SELECT dc_vert.item,
                           dc_vert.loc,
                           dc_vert.loc_type,
                           dc_vert.source_method,
                           dc_vert.primary_supp,
                           w.primary_vwh source_wh,
                           dc_vert.actie,
                           MAX(dc_vert.actie) OVER (PARTITION BY dc_vert.item, dc_vert.loc) actie_max,
                           COUNT(dc_vert.primary_supp) OVER (PARTITION BY dc_vert.item, dc_vert.loc) primary_count
                    FROM   dc_item_loc_pim_lms dc_vert,
                           item_supplier isu,
                           store sto,
                           wh w
                    WHERE  dc_vert.primary_supp IS NOT NULL
                       AND isu.item = dc_vert.item
                       AND dc_vert.primary_supp = isu.supplier
                       AND w.wh = dc_vert.source_wh
                       AND sto.store = dc_vert.loc
                       AND isu.supp_discontinue_date >= SYSDATE)
            WHERE  actie = actie_max AND primary_count = 1) itemloc
ON         (il.item = itemloc.item AND il.loc = itemloc.loc)
WHEN MATCHED THEN
   UPDATE SET
      il.source_method          = itemloc.source_method,
      il.loc_type               = itemloc.loc_type,
      il.primary_supp           = itemloc.primary_supp,
      il.source_wh              = itemloc.source_wh,
      il.last_update_datetime   = SYSDATE;
0 голосов
/ 02 февраля 2012

Я бы предложил вам использовать современный синтаксис объединения

FROM
    dc_item_loc_pim_lms dc_vert
    INNER JOIN item_supplier isu
       ON dc_vert.item = isu.item AND
          dc_vert.primary_supp = isu.supplier
    INNER JOIN store sto
       ON dc_vert.loc = sto.store
    INNER JOIN wh w
       ON dc_vert.source_wh = w.wh
WHERE
    dc_vert.primary_supp IS NOT NULL AND
    isu.supp_discontinue_date >= SYSDATE
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...