Массовое обновление в Oracle 12.1.0.2? - PullRequest
0 голосов
/ 18 октября 2018

В настоящее время я работаю над задачей, и мне необходимо обновить около 2000 до 4000 записей, считывая значения из JSON.Я оптимизирую часть JSON, но в настоящее время я обновляю каждую запись одну за другой.Может ли кто-нибудь предложить лучший подход для обновления всех записей от 2000 до 4000 с помощью одного запроса вместо того, чтобы запускать его от 2000 до 4000 раз?Вот мой пример кода

    APEX_JSON.PARSE(V_OUTPUT_DATA); 
plan_count := apex_json.get_count('plan'); 
IF plan_count > 0 THEN 
    FOR I in 1..plan_count LOOP 
        activities_count := APEX_JSON.get_count(p_path => 'plan['||i||'].activities'); 
        IF activities_count > 0 THEN 
            FOR j in 2..(activities_count-1) LOOP 
                V_TASK_ID := APEX_JSON.get_varchar2(p_path => 'plan['||i||'].activities['||j||'].task_id'); 
                V_SEQ := APEX_JSON.get_number(p_path => 'plan['||i||'].activities['||j||'].sequence');
                UPDATE TABLE_NAME 
                SET ROUTE_SEQUENCE = V_SEQ, UPDATED_BY = 'SYSTEM',UPDATED_ON = SYSTIMESTAMP 
                WHERE TASK_ID = V_TASK_ID; 
            END LOOP; 
            COMMIT; 
        END IF; 
    END LOOP;       
END IF;

Должен ли я использовать 2D-массив и использовать его для массового обновления, или можно использовать какой-то другой подход?

Образец JSON добавлен

{
"plan": [{
    "vehicle_id": "vehicle_1",
    "activities": [{
        "sequence": 0,
        "timestamp": "2017-11-10T09:48:19Z",
        "location_id": "depot"
    },
    {
        "sequence": 1,
        "timestamp": "2017-11-10T09:50:07Z",
        "task_id": "465427",
        "location_id": "465427",
        "travel_distance": 1099,
        "travel_duration": "00:01:48"
    },
    {
        "sequence": 2,
        "timestamp": "2017-11-10T09:50:10Z",
        "task_id": "443951",
        "location_id": "443951",
        "travel_distance": 26,
        "travel_duration": "00:00:03"
    },
    {
        "sequence": 3,
        "timestamp": "2017-11-10T09:50:25Z",
        "task_id": "165760",
        "location_id": "165760",
        "travel_distance": 152,
        "travel_duration": "00:00:15"
    },
    {
        "sequence": 4,
        "timestamp": "2017-11-10T09:51:34Z",
        "task_id": "459187",
        "location_id": "459187",
        "travel_distance": 705,
        "travel_duration": "00:01:09"
    }]
  }]
}

1 Ответ

0 голосов
/ 18 октября 2018

Предполагая, что ваша таблица похожа на эту:

  create table table_name 
  ( 
     id number(12) primary key,
     route_sequence number(12),
     updated_by varchar2(30),
     updated_on timestamp(9)  
  )  

и что объект json похож на этот:

  {
       "activities": 
        [
            {"task_id": 1, "sequence" : 10},
            {"task_id": 2, "sequence" : 20},
            {"task_id": 3, "sequence" : 30},
            {"task_id": 4, "sequence" : 40},
            {"task_id": 5, "sequence" : 50},
        ]
  }

Вы можете напрямую запрашивать данные json в SQL, используяSQL-оператор "JSON_TABLE" (новичок в oracle 12 - см. https://docs.oracle.com/database/121/SQLRF/functions092.htm#SQLRF56973)..., а затем вы можете воспользоваться этим, используя такой запрос в операторе "слияния":

этот единственный оператор SQL делаетчто вам нужно:

 merge into table_name t
 using
 (
      select * 
      from JSON_TABLE(
              '{
                   "activities": 
                   [
                       {"task_id": 1, "sequence" : 10},
                       {"task_id": 2, "sequence" : 20},
                       {"task_id": 3, "sequence" : 30},
                       {"task_id": 4, "sequence" : 40},
                       {"task_id": 5, "sequence" : 50},
                   ]
              }', 
              '$."activities"[*]'

              COLUMNS(    
                       V_TASK_ID  NUMBER   PATH '$.task_id',
                       V_SEQ    NUMBER   PATH '$.sequence'
                  )
              )
 ) json_data
 on (json_data.v_task_id = t.id)
 when matched then 
    update set 
      ROUTE_SEQUENCE = V_SEQ,
      UPDATED_BY = 'SYSTEM',
      UPDATED_ON = SYSTIMESTAMP                  

Редактировать: теперь, когда вы опубликовали свой фактический пример json:

, чтобы мой пример работал с вашими данными, вам просто нужно заменить

 '$."activities"[*]'

строка с этим:

 '$."plan"[0]."activities"[*]'

вещь может стать более сложной, если элемент массива «план» содержит более одного элемента, но это все еще можно сделать.


Редактировать 2: как обрабатывать вложенные объекты (то есть: что делать, когда «план» содержит несколько объектов

Предположим, что строка json, которая должна быть обработана, является этой

    '{
        "plan": 
         [
              {
                  "vehicle_id": "vehicle_1",
                  "activities": 
                   [
                       {
                           "sequence": 1,
                           "task_id": "465427"
                       },
                       {
                           "sequence": 2,
                           "task_id": "443951"
                       }
                   ]    
              }
              ,
              {
                  "vehicle_id": "vehicle_2",
                  "activities": 
                   [
                       {
                           "sequence": 3,
                           "task_id": "165760"
                       },
                       {
                           "sequence": 4,
                           "task_id": "459187"
                       }
                   ]
               }
          ]
    }'

(Я не буду повторять это в моих примерах: я просто напишу в коде

Если вы не заинтересованы в чтении поля vehicle_id и хотите получить подробное представление обо всех подробностях действий (независимо от того, какой объект «плана» содержит их, вы можете просто изменить строку селектора корневого объекта из этого * 1034)*

 '$."plan"[0]."activities"[*]'

на это:

 '$."plan"[*]."activities"[*]'

так, этот запрос:

 select * 
 from JSON_TABLE
   (
       <json_string_here>,
       '$."plan"[*]."activities"[*]'
        COLUMNS(    
                V_TASK_ID  NUMBER   PATH '$.task_id',
                V_SEQ    NUMBER   PATH '$.sequence'
        )
   )

будет проходить через все объекты "деятельности" всех объектов плана, но он будет возвращатьВы только столбцы "task_id" и "sequence".

traversing only the leaf details

Если вы хотите вместо этого также повторить соответствующий столбец идентификатора транспортного средства во всех строках, вы должны перейти на уровень с корневым селектором, используя этоВыражение

'$."plan"[*]'

и внутри предложения «columnns» вы можете использовать синтаксис «вложенного пути», чтобы указать, что вы хотите расширить встроенные столбцы подобъекта:

   select * 
   from JSON_TABLE
   (
        <json_string_here>,
        '$."plan"[*]'
        COLUMNS
        ( 
            VEHICLE  varchar2(20) PATH '$."vehicle_id"',
            NESTED PATH '$."activities"[*]'
               COLUMNS
               (
                     V_TASK_ID  NUMBER   PATH '$.task_id',
                     V_SEQ    NUMBER   PATH '$.sequence'
                )
        )
   ) 

expanding subobject columns

...