2013-04-22 4 views
3

Я использую процедуру PL/SQL для вставки значений из XML в реляционные таблицы. XML-файл находится в столбце XMLTYPE.
Колонны таблицы (OFFLINE_XML), содержащие XML являются
Разбор PL/SQL XML в реляционные таблицы

ID, XML_FILE, STATUS 

Есть две таблицы, в которой я хочу, чтобы вставить значения, т.е. ПОДРАЗДЕЛЕНИЕ и РАЗДЕЛЫ Структура ОТДЕЛ как в соответствии с: -

ID, NAME 

Структура таблицы разделов: -

ID, NAME, DEPARTMENT_ID 

Теперь есть третья таблица (LIST_1) в бее ch i хочу вставить значения, которые уже существуют в обеих вышеупомянутых таблицах.
Структура LIST_1 является: -

ID, DEPARTMENT_ID,DEPARTMENT_NAME,SECTIONS_ID, SECTIONS_NAME 

формат XML, как в соответствии: -

<ROWSET> 
<DEPARTMENT> 
    <DEPARTMENT_ID>DEP22681352268280797</DEPARTMENT_ID> 
    <DEPARTMENT_NAME>myDEPARTMENT</DEPARTMENT_NAME> 
    <SECTIONS_ID>6390135666643567</SECTIONS_ID> 
    <SECTIONS_NAME>mySection</SECTIONS_NAME> 
</DEPARTMENT> 
<DEPARTMENT> 
    <DEPARTMENT_ID>DEP255555555550797</DEPARTMENT_ID> 
    <DEPARTMENT_NAME>myDEPARTMENT2</DEPARTMENT_NAME> 
    <SECTIONS_ID>63901667779243567</SECTIONS_ID> 
    <SECTIONS_NAME>mySection2</SECTIONS_NAME> 
</DEPARTMENT> 
</ROWSET> 


DECLARE 
    BEGIN 
    insert all 
     into department (id, name) 
      values (unit_id, unit_name) 
     into sections (id, name, department _id) 
      values (sect_id, sect_name, department _id) 
    select department .id as department _id 
      , department.name as department_name 
      , sect.id as sect_id 
      , sect.name as sect_name 
    from OFFLINE_XML 
     , xmltable('/ROWSET/DEPARTMENT' 
        passing OFFLINE_XML.xml_file 
        columns 
         "ID" varchar2(20) path 'UNIT_ID' 
         , "NAME" varchar2(20) path 'UNIT_NAME' 
       ) department 
      , xmltable('/ROWSET/DEPARTMENT' 
       passing OFFLINE_XML.xml_file 
       columns 
        "ID" varchar2(20) path 'SECTIONS_ID' 
        , "NAME" varchar2(20) path 'SECTIONS_NAME' 
      ) sect 
       where status = 3; 
    EXCEPTION 
    WHEN DUP_VAL_ON_INDEX THEN 
    dbms_output.put_line('Duplicate='|| department.id); 
    --insert into LIST_1 values(ID,DEPARTMENT_ID, SECTIONS_ID, DEPARTMENT_NAME,SECTIONS_NAME); 
END; 

Теперь проблема заключается в том, что как я могу вставить или определить значения на основе первичного ключа, который уже существует в таблице DEPARTMENT и SECTIONS и после этого вставляет существующие значения в таблицу LIST_1. ------ Обновленное усилие --------------

Я придумал другое решение, но это снова дает мне проблемы. В указанной процедуре курсор имеет тенденцию повторяться для каждого xquery. Я не знаю, как я буду решать этот вопрос ..

DECLARE 
    department_id varchar2(20); 
    department_name varchar2(20); 
    sect_id varchar2(20); 
    sect_name varchar2(20); 
    sections_unit_id varchar2(20); 
    var number; 
    CURSOR C1 IS 
    select 
      sect.id as sect_id 
      , sect.name as sect_name 
      , sect.unit_id as sections_unit_id 
    from OFFLINE_XML 
      , xmltable('/ROWSET/DEPARTMENT' 
        passing OFFLINE_XML.xml_file 
        columns 
         "ID" varchar2(20) path 'UNIT_ID' 
         , "NAME" varchar2(20) path 'UNIT_NAME' 
       ) DEPARTMENT 
      , xmltable('/ROWSET/DEPARTMENT' 
       passing OFFLINE_XML.xml_file 
       columns 
        "ID" varchar2(20) path 'SECTIONS_ID' 
        , "NAME" varchar2(20) path 'SECTIONS_NAME' 
        , "DEPARTMENT_ID" varchar2(20) path 'DEPARTMENT_ID' 
      ) sect 
       where status = 3; 

BEGIN 
     FOR R_C1 IN C1 LOOP 
     BEGIN 
     var :=1; 
     --insert into sections_temp_1 (id, name)values (R_C1.sect_id, R_C1.sect_name); 
     -- commit; 
      dbms_output.put_line('Duplicate='||var); 
     EXCEPTION 
     WHEN DUP_VAL_ON_INDEX THEN 
     dbms_output.put_line('Duplicate='||R_C1.sect_id); 
     END; 
     var:=var+1; 
     END LOOP; 

END; 

ответ

2

Кажется, что вам нужно немного сложнее XQuery для извлечения строк из поля XMLType.

Нет необходимости извлекать разделы и отделы отдельно, и после этого попытайтесь сопоставить его.

Попробуйте этот вариант:

select 
    department_id, 
    department_name, 
    sections_id, 
    sections_name 
from 
    OFFLINE_XML xml_list, 
    xmltable(
    ' 
     for $dept in $param/ROWSET/DEPARTMENT 
     return $dept 
    ' 
    passing xml_list.xml_file as "param" 
    columns 
     "DEPARTMENT_ID" varchar2(100) path '//DEPARTMENT/DEPARTMENT_ID', 
     "DEPARTMENT_NAME" varchar2(4000) path '//DEPARTMENT/DEPARTMENT_NAME', 
     "SECTIONS_ID"  varchar2(100) path '//DEPARTMENT/SECTIONS_ID', 
     "SECTIONS_NAME" varchar2(4000) path '//DEPARTMENT/SECTIONS_NAME' 
) section_list 
where 
    xml_list.Status = 3 

SQL fiddle - 1

После того, что вы получили набор данных, который может быть внешним присоединился к существующим таблицам на это первичные ключи (или что-то другое - зависит от требуемой логики) если вы хочу найти, если какие-либо значения уже существует:

select 
    offline_set.offline_xml_id, 
    offline_set.department_id, 
    offline_set.department_name, 
    offline_set.sections_id, 
    offline_set.sections_name, 
    nvl2(dept.id,'Y', 'N') is_dept_exists, 
    nvl2(sect.id,'Y', 'N') is_sect_exists 
from 
    ( 
    [... skipped text of previous query ...] 
) offline_set, 
    department dept, 
    sections sect 
where 
    dept.id (+) = offline_set.department_id 
    and 
    sect.id (+) = offline_set.sections_id 

SQL fiddle - 2

Поскольку я действительно не осведомлен о логике, лежащей в основе этих требований, я не могу предложить никаких будущих инструкций по обработке. Но кажется, что вы пропустили ссылку на таблицу OFFLINE_XML в LIST_1, которая должна была идентифицировать источник ошибок/дубликатов.

0

Лучший способ сделать это было бы с Oracle встроенной в регистрации ошибок. Используйте DBMS_ERRLOG.CREATE_ERROR_LOG() для создания таблицы протоколирования для каждой целевой таблицы (т. Е. СЕКЦИИ и ОТДЕЛ в вашем случае). Find out more.

Синтаксис для использования этих таблиц с INSERT ALL не является интуитивно понятным, но это то, что нужно сделать:

insert all 
    into department (id, name) 
     values (unit_id, unit_name) 
     log errors into err$_department ('XML Load failure') 
    into sections (id, name, department_id) 
     values (sect_id, sect_name, department_id) 
     log errors into err$_section ('XML Load failure') 
select department.id as department_id 
     .... 

Вы можете поместить любой (короткое иш) строку в метку журнала ошибок, но убедитесь, что он то, что поможет вам в местных соответствующих записях. Возможно, вы захотите установить значение REJECT LIMIT для некоторого значения в зависимости от того, хотите ли вы выполнить сбой по одной (или нескольким) ошибкам или обработать весь XML и отсортировать его впоследствии. Find out more.


Я предлагаю вам использовать отдельные журналы для каждой целевой таблиц, а один журнал для обоих по двум причинам:

  1. В моих expereince решений, встроенные в Feartures LEVERAGE Oracle, как правило, лучше масштабируются и более надежный, чем ручной рулон.
  2. Это лучше подходит для того, что может случиться.У вас есть три обстоятельства, которые могут вызвать загрузки швырнуть DUP_VAL_ON_INDEX:
    • запись имеет дубликат отдела ID
    • запись имеет дубликат Раздел ID
    • запись имеет дубликат отдела ID и дубликата Раздел ID

Отдельные таблицы облегчают понимание того, что пошло не так. Это большое преимущество при загрузке больших объемов данных.

«я должен сообщить моему пользователю, что это много повторяющихся записей были найдены в XML»

Вы все еще можете сделать это с двумя журналами ошибок. Черт, вы можете даже присоединиться к журналам ошибок в виде LIST_1, это очень важно для вас.

+0

Интересно, как это поможет мне вставлять уже существующие значения в таблицу DEPARTMENT и SECTIONS в таблицу LIST_1? –

+0

Я предполагаю, что у вас есть первичные ключи, определенные в этих таблицах: в этом случае LOG ERROR INTO будет обрабатывать уникальные нарушения ключа, записывая дубликаты записей в таблицы журналов. – APC

+0

То есть, используйте отдельные журналы для каждой целевой таблицы, а не одну таблицу для обоих. – APC

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