2016-01-14 10 views
0

Мне нужно обновить значения XML, хранящиеся в столбце BLOB в Oracle 11G. BLOB хранит XML-файл кометы, в котором мне нужно обновить некоторые значения и сохранить его как BLOB. Как я могу легко SELECT и UPDATE преобразование blit данных wit и XMLQUERY AND XMLUPDATE? Любые примеры кода?Выбрать и обновить столбец Oracle BLOB с помощью XMLQUERY

Заранее спасибо.

Вот еще некоторые детали:

Здесь вы DDL таблицы:

CREATE TABLE MAPSHEET 
(
    MAPSHEETID NUMBER (14,0) NOT NULL, 
    NAME VARCHAR2 (64) NOT NULL, 
    STRUCTURE BLOB, 
) 

данные XML в блоб Col СТРУКТУРЫ

<MapSheet Version="1.0"> 
    <Frame> 
     <JobId>9022165</JobId> 
     <LayoutId>24807064</LayoutId> 
     <Blocks> 
      <Block MapFieldMask="true" CompressText="false" CombineRaster="false"> 
       <Name>layout</Name> 
       <StyleId>24808857</StyleId> 
       <LayoutLayers>0 1</LayoutLayers> 
       <BlockScale/> 
       <JobItemIds/> 
      </Block> 
      <Block MapFieldMask="true" CompressText="false" CombineRaster="false"> 
       <Name>karto</Name> 
       <StyleId>24809031</StyleId> 
       <LayoutLayers>4</LayoutLayers> 
       <BlockScale/> 
       <JobItemIds> 
        <JobItemId>9083675</JobItemId> 
        <JobItemId>9088148</JobItemId> 
       </JobItemIds> 
      </Block> 
      <Block MapFieldMask="true" CompressText="false" CombineRaster="false"> 
       <Name>hel</Name> 
       <StyleId>24809032</StyleId> 
       <LayoutLayers>-</LayoutLayers> 
       <BlockScale/> 
       <JobItemIds> 
        <JobItemId>9022173</JobItemId> 
        <JobItemId>25403646</JobItemId> 
       </JobItemIds> 
      </Block><Block MapFieldMask="true" CompressText="false" CombineRaster="false"> 
       <Name>shade glacier</Name> 
       <StyleId>24809041</StyleId> 
       <LayoutLayers>-</LayoutLayers> 
       <BlockScale/> 
       <JobItemIds> 
        <JobItemId>24806040</JobItemId> 
       </JobItemIds> 
      </Block> 
      <Block MapFieldMask="true" CompressText="false" CombineRaster="false"> 
       <Name>shade</Name> 
       <StyleId>24809040</StyleId> 
       <LayoutLayers>-</LayoutLayers> 
       <BlockScale/> 
       <JobItemIds> 
        <JobItemId>24806038</JobItemId> 
       </JobItemIds> 
      </Block> 
     </Blocks> 
     <Offset X="0" Y="0"/> 
     <Name>DS</Name> 
    </Frame></MapSheet> 

Этот простой SELECT, чтобы получить данные не работают:

SELECT x.MapSheet 
FROM XmlTable('/MapSheet') PASSING XmlType(MAPSHEET.STRUCTURE,1) 
    COLUMS "XML" VARCHAR2(300) PATH 'MapSheet') AS x; 

Как я могу выбрать/обновить требуемые данные xml из colob blob?

ответ

0

Для выбора из XML вы можете использовать ExtractValue(XmlType, XPath) или XmlTable, чтобы преобразовать Xml clob в запрашиваемую таблицу XML. Для конвертирования BLOB вы можете просто обернуть его XmlType(blob_value, 1), тогда вы можете выполнить любую из связанных с ним функций XML.

SELECT ExtractValue(
      XmlType('<test><node1>value1</node1><node2>value2</node2></test>'), 
        '/test/node1') as Node1 
FROM dual; 

Или с помощью XmlTable

SELECT xt.Node1, xt.Node2 
FROM XmlTable('/test/block' 
     PASSING XmlType('<test> 
<block><node1>value1a</node1><node2>value2a</node2></block> 
<block><node1>value1b</node1><node2>value2b</node2></block> 
<block><node1>value1c</node1><node2>value2c</node2></block> 
</test>') 
     COLUMNS 
     "Node1"  VARCHAR2(20) PATH 'node1', 
     "Node2"  VARCHAR2(20) PATH 'node2') AS xt; 

Использование UpdateXml, предполагая, что запись Я обновляю имеет выше XML в столбце:

UPDATE MyTable SET xml_data = 
UpdateXml(xml_data, '/test/block/node2[text() = "value2b"]/text()', 'value2z') 
WHERE data_id = 1; 

выше следует обновить node2 что имел значение value2b, а теперь имеет value2z. Затем возвращается новый XML и присваивает его столбцу xml_data в записи, которая соответствует data_id = 1.

Одно замечание, в приведенном выше запросе, оно работает со столбцом, который уже имеет тип XmlType. Вы работаете с BLOB. Я бы спросил, есть ли причина для этого: BLOB вместо CLOB или XmlType? Если вы храните данные типа VARCHAR, вы действительно должны использовать один из двух последних типов: CLOB, если вы храните различные данные VARCHAR и XmlType (это более конкретный тип CLOB), если вы храните строго XML-данные.

Если вы застряли с использованием типа данных BLOB, вам нужно будет выполнить много конверсий. Используя XmlType(blob_data, 1), вы должны получить от BLOB до XmlType, но, вернувшись, вам, вероятно, понадобится использовать UTL_RAW.CAST_TO_RAW(xml_data).Таким образом, запрос стал бы:

UPDATE MyTable SET clob_data = 
UTL_RAW.CAST_TO_RAW(
    UpdateXml(XmlType(clob_data, 1), '/test/block/node2[text() = "value2b"]/text()', 'value2z').GetClobVal() 
) 
WHERE data_id = 1; 

Вот рабочий самостоятельный пример, показывающий различные методы, упомянутые выше:

DECLARE varchar_data VARCHAR2(500); 
     blob_data  BLOB; 
     xml_data  XMLType; 
     node1Val  VARCHAR(20); 
     node2Val  VARCHAR(20); 

BEGIN 
    select '<test> 
<group><node1>value1a</node1><node2>value2a</node2></group> 
<group><node1>value1b</node1><node2>value2b</node2></group> 
<group><node1>value1c</node1><node2>value2c</node2></group> 
<group><node1>value1d</node1><node2>value2d</node2></group> 
</test>' into varchar_data from dual; 

    select UTL_RAW.CAST_TO_RAW(varchar_data) into blob_data from dual; 

    select XmlType(blob_data, 1) into xml_data from dual; 
    dbms_output.put_line(xml_data.getClobVal()); 

    select xt.Node1, xt.Node2 
    into node1Val, node2Val 
    from XmlTable('/test/group' 
     passing XmlType(blob_data, 1) 
     columns Node1  VARCHAR2(20) path 'node1', 
       Node2  VARCHAR2(20) path 'node2' 
     ) xt 
    where xt.Node1 = 'value1c'; 
    dbms_output.put_line('node1Val = ''' || node1Val || ''', node2Val = ''' || node2Val || ''';'); 

    -- Using UpdateXml to update the XML, that will return an XmlType 
    -- so we call GetClobVal() to let CAST_TO_RAW convert to BLOB. 
    select UTL_RAW.CAST_TO_RAW(
     UpdateXml(
      XmlType(blob_data, 1), 
      '/test/group/node2[../node1/text() = "value1c"]/text()', 
      'zzzz').GetClobVal() 
     ) into blob_data 
    from dual; 

    select XmlType(blob_data, 1) into xml_data from dual; 
    dbms_output.put_line(xml_data.getClobVal()); 

    select xt.Node1, xt.Node2 
    into node1Val, node2Val 
    from XmlTable('/test/group' 
     passing XmlType(blob_data, 1) 
     columns Node1  VARCHAR2(20) path 'node1', 
       Node2  VARCHAR2(20) path 'node2' 
     ) xt 
    where xt.Node1 = 'value1c'; 
    dbms_output.put_line('node1Val = ''' || node1Val || ''', node2Val = ''' || node2Val || ''';'); 

END; 
+0

Привет, я не могу использовать EXTRACTVALUE команды больше, потому что это не рекомендуется. Поэтому я должен попробовать его с помощью XmlTable в вашем примере. Но отсутствует преобразование blob для clob и то же самое для оператора update, простой метод обхода вокруг метода XMLType (blob_value) не работает. Можете ли вы добавить полный синтаксис для него. Было бы замечательно! – happymapper

+0

@happymapper - Извините, забыл включить параметр для указания набора символов (1 = USASCII) в функции 'XmlType'. – gmiley

+0

Ваш пример выбора все еще не работает, потому что синтаксис XMLType по-прежнему использует данные XML. Блаб используется в нашей таблице, потому что это настройка по умолчанию для нашей системы, и я не должен ее менять. – happymapper

0
create table testxmlBlob (p blob); 

Вставьте некоторые XML-документ в таблицу.

insert into testxmlBlob values(utl_raw.cast_to_raw('<?xml version="1.0"?> 
<catalog> 
    <book id="bk101"> 
     <author>Gambardella, Matthew</author> 
     <title>XML Developer''s Guide</title> 
     <genre>Computer</genre> 
     <price>44.95</price> 
     <publish_date>2000-10-01</publish_date> 
     <description>An in-depth look at creating applications 
     with XML.</description> 
    </book> 
    <book id="bk102"> 
     <author>Ralls, Kim</author> 
     <title>Midnight Rain</title> 
     <genre>Fantasy</genre> 
     <price>5.95</price> 
     <publish_date>2000-12-16</publish_date> 
     <description>A former architect battles corporate zombies, 
     an evil sorceress, and her own childhood to become queen 
     of the world.</description> 
    </book></catalog>')) ; 

Просмотреть добавленный xml. xmltype(blob,csid -charset enocoding id '0' is default)

select xmlserialize(document xmltype(p,0)) from testxmlBlob; 

Использование XMLQUERY изменить <description> к <descriptionNew>. он также может быть использован в обновлении заявлении update testxmlBlob set p = XMLQuery(....) ...

select XMLQuery('copy $i := $p1 
       modify 
       (
      for $j in $i/catalog/book/description 
      let $newn := <descriptionNew>newDescription</descriptionNew> 
      return replace node $j with $newn) 
      return $i    
      ' PASSING xmltype(p,0) AS "p1"  
      RETURNING CONTENT) readable 
      ,xmlserialize(document XMLQuery('copy $i := $p1 
       modify 
       (
      for $j in $i/catalog/book/description 
      let $newn := <descriptionNew>newDescription</descriptionNew> 
      return replace node $j with $newn) 
      return $i    
      ' PASSING xmltype(p,0) AS "p1" 
      RETURNING CONTENT) as BLOB) blob_value 
      from testxmlBlob; 

Other example how to use xmlquery to update

+0

Большое спасибо! Теперь все хорошо! – happymapper

Смежные вопросы