Обновление данных JSON, хранящихся в CLOB в Db2

Я хочу выполнить обновление данных JSON, хранящихся в столбце CLOB в таблице Db2.

Например, часть данных CLOB в настоящее время выглядит так

 "commercialOfferPersonRoleList" : [ {
          "commercialOfferPersonRolePK" : {
            "commercialOfferId" : 100000000008817
          },
          "personId" : {
            "personID" : "1000019579"
          }
         },
         "roleBusinessPartner" : {
          "value" : 1
        }
       ]

и после обновления я хочу, чтобы это выглядело так

"commercialOfferPersonRoleList" : [ {
              "commercialOfferPersonRolePK" : {
                "commercialOfferId" : 100000000008817
              },
              "personId" : {
                "personID" : "1000019579"
              },
              "roleBusinessPartner" : {
              "value" : 1
               }
             }
            ]

Когда наше приложение срабатывает, значения заполняются в соответствующих тегах, и это значение CLOB сохраняется в таблице. Из-за некоторых изменений мне нужно аналогичным образом обновить значения COLB почти для 10 000 записей.

Есть ли способ написать общий скрипт для реализации такого изменения?

Раньше я использовал xquery для обновления структуры XML, но здесь нам нужно изменить положение тега вместе с соответствующим значением, и на этот раз это данные JSON.

просто чтобы упростить, моя цель:

before Update :

                            commercialOfferPersonRolePK
                                         |
               ----------------------------------------------------
               |                                                  |
    -----------------------------                            roleBusinessPartner
    |                           |
    commercialOfferId         personId

после обновления:

  commercialOfferPersonRolePK
           |                                                  
----------------------------------------------------------                            
|                           |                            |
commercialOfferId         personId                   roleBusinessPartner

person Ketan_Gupta    schedule 14.09.2018    source источник
comment
Что вы подразумеваете под общим скриптом? Отсутствие } означает, что предыдущее значение не является допустимым XML, поэтому вы не сможете использовать для него функции XML. Если бы вы использовали тип данных XML для столбца, недопустимые данные не были бы допущены в первую очередь. Какова общая длина ваших значений CLOB и какую версию DB2 вы используете, это повлияет на то, какие функции вы можете использовать для обновления CLOB.   -  person Paul Vernon    schedule 14.09.2018
comment
Пример, который я привел, это всего лишь часть xml, а не весь xml.   -  person Ketan_Gupta    schedule 14.09.2018
comment
Атрибут был определен следующим образом: DATA_OBJECT CLOB(1048576) INLINE LENGTH 164 NOT NULL. Мы используем DB2 V10.5   -  person Ketan_Gupta    schedule 14.09.2018
comment
какова его фактическая максимальная используемая длина. Например, SELECT MAX(LENGTH(DATA_OBJECT_CLOB)) FROM table   -  person Paul Vernon    schedule 14.09.2018
comment
567515 - максимальная длина   -  person Ketan_Gupta    schedule 14.09.2018
comment
Итак, вы можете использовать REPLACE, так как длина меньше 1 048 576 байт. ibm.com/support/knowledgecenter/en/SSEPGG_11.1.0/   -  person Paul Vernon    schedule 14.09.2018
comment
Являются ли данные действительными данными JSON? Какую версию Db2 вы используете?   -  person Paul Vernon    schedule 14.09.2018


Ответы (2)


Для данных JSON, начиная с Db2 11.1.3.3, используйте SYSTOOLS.JSON_UPDATE для обновления значений JSON.

https://www.ibm.com/support/knowledgecenter/en/SSEPGG_11.1.0/com.ibm.swg.im.dbclient.json.doc/doc/r0070292.html

Вам нужно будет преобразовать данные в BSON с помощью SYSTOOLS.JSONTOBSON, а затем снова с помощью SYSTOOLS.BSONTOJOSN после обновления.

Например. что-то вроде этого

values 
  SYSTOOLS.BSON2JSON(
    SYSTOOLS.JSON_UPDATE(
      SYSTOOLS.JSON2BSON(
    '{ "commercialOfferPersonRoleList" : 
        [ 
            {    "commercialOfferPersonRolePK" : { "commercialOfferId" : 100000000008817 } 
             ,   "personId" : {  "personID" : "1000019579" } 
            }
        ,   {"roleBusinessPartner" : { "value" : 1 } }
        ]
     }')
     , '{ $set:
      { "commercialOfferPersonRoleList" : 
        [ 
            {"commercialOfferPersonRolePK" : { "commercialOfferId" : 100000000008817  } }
        ,   {"personId" : {  "personID" : "1000019579" } }
        ,   {"roleBusinessPartner" : { "value" : 1 } }
        ]
     }
     }'
     ))
person Paul Vernon    schedule 14.09.2018
comment
Спасибо за ваш вклад, Вернон! Однако у меня есть 10 000 таких значений clob для обновления, поэтому будет сложно написать запрос для каждого из этих clob. Теги и структура одинаковы во всех clobs, но их соответствующие значения различны. Есть ли какое-либо общее решение, которое может помочь мне обновить несколько записей одновременно. Мы будем использовать атрибут метки времени для идентификации набора целевых записей. - person Ketan_Gupta; 14.09.2018

Немного регулярного выражения может решить вашу проблему.. зависит от того, насколько сложна ваша полная проблема... например.

create table clob(c clob(1M))
;                  
insert into clob values ('{ "commercialOfferPersonRoleList" : 
            [ 
                {"commercialOfferPersonRolePK" : { "commercialOfferId" : 100000000008817  } 
            ,   "personId" : {  "personID" : "1000019579" } }
            ,   {"roleBusinessPartner" : { "value" : 1 } }
            ]
         }')
      ;   
select regexp_replace(c,'(,\s*)("personId"(.*?\}){1}?)\s*\}', '} \1 { \2 }', 1, 0, 'n') from clob;

который возвращает

{ "commercialOfferPersonRoleList" : 
            [ 
                {"commercialOfferPersonRolePK" : { "commercialOfferId" : 100000000008817  } 
            } ,    { "personId" : {  "personID" : "1000019579" } }
            ,   {"roleBusinessPartner" : { "value" : 1 } }
            ]
         }

Так что вы могли бы сделать, например.

update clob set c = regexp_replace(c,'(,\s*)("personId"(.*?\}){1}?)\s*\}', '} \1 { \2 }',1,0,'n')
              where regexp_like   (c,'(,\s*)("personId"(.*?\}){1}?)\s*\}'               ,1  ,'n');

Я предлагаю вам использовать SYSTOOLS.JSON2BSON, чтобы убедиться, что преобразованный большой двоичный объект все еще действителен в формате JSON, прежде чем вы действительно запустите обновление.

в этом примере я могу запустить это, чтобы проверить, что обновленный столбец все еще действителен JSON

select SYSTOOLS.BSON2JSON(SYSTOOLS.JSON2BSON(c)) from clob
person Paul Vernon    schedule 14.09.2018