Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Очень долгий разбор XML / 15 сообщений из 15, страница 1 из 1
15.08.2016, 09:18
    #39291731
mozgen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Очень долгий разбор XML
Доброго времени суток Господа Ораклоиды. Прошу помощи в разборе XML.
Собственно ситуация:
Имею относительно небольшой XML файл, из которого средствами SQL необходимо разобрать порядка 1К элементов и выбрать в таблицу те атрибуты (Position, Length, DefectValue, Class, SensorID) в которых атрибут Aggregate равен заданному значению.
Наверно как-то запутано получилось...
Пример XML:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
<Results ID="0001">
    <Defect REC_NO="66" Position="3.0500000000000003" Length="0.1" DefectValue="104.87" Class="X" Aggregate="PM" SensorID="20"/>
    <Defect REC_NO="67" Position="4.07" Length="0.1" DefectValue="179.74" Class="X" Aggregate="PM" SensorID="1"/>
    <Defect REC_NO="68" Position="4.07" Length="0.1" DefectValue="149.95000000000002" Class="X" Aggregate="PM" SensorID="2"/>
    <Defect REC_NO="69" Position="4.07" Length="0.1" DefectValue="18.82" Class="X" Aggregate="PM" SensorID="4"/>
    <Defect REC_NO="70" Position="4.07" Length="0.1" DefectValue="74.58" Class="X" Aggregate="PM" SensorID="5"/>
    <Defect REC_NO="71" Position="4.07" Length="0.1" DefectValue="37.34" Class="X" Aggregate="PM" SensorID="13"/>
    <Defect REC_NO="72" Position="4.07" Length="0.1" DefectValue="38.050000000000004" Class="X" Aggregate="PM" SensorID="14"/>
    <Defect REC_NO="73" Position="4.07" Length="0.1" DefectValue="0.11" Class="X" Aggregate="PM" SensorID="17"/>
 ...
    <Defect REC_NO="1137" Position="79.725000000000009" Length="0.03" DefectValue="0" Class="E" Aggregate="VS" SensorID="3"/>
    <Defect REC_NO="1138" Position="80.693" Length="0.03" DefectValue="0" Class="P" Aggregate="VS" SensorID="4"/>
</Results>



Допустим, мне необходимо получить значения Position, Length, DefectValue, Class, SensorID, где Aggregate="PM".

Делаю так:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
val:=1;
loop
  exit when val = PM_Count; -- количество элементов
  select b.DESKRIPTION.EXTRACT('/Billet/NDTResults/Defect[position()='||val||']/@Aggregate').getstringval() into agregate FROM TBLXML b where id = 749417;
  if agregate='PM' then
    select b.DESKRIPTION.EXTRACT('/Billet/NDTResults/Defect[position()='||val||']/@Position').getstringval() into DefectPos FROM TBLXML b where id = 749417;
    select b.DESKRIPTION.EXTRACT('/Billet/NDTResults/Defect[position()='||val||']/@Length').getstringval() into DefectLength FROM TBLXML b where id = 749417;
    select b.DESKRIPTION.EXTRACT('/Billet/NDTResults/Defect[position()='||val||']/@DefectValue').getstringval() into DefectAmplitude FROM TBLXML b where id = 749417;
    select b.DESKRIPTION.EXTRACT('/Billet/NDTResults/Defect[position()='||val||']/@Class').getstringval() into DefectClass FROM TBLXML b where id = 749417;
    select b.DESKRIPTION.EXTRACT('/Billet/NDTResults/Defect[position()='||val||']/@SensorID').getstringval() into SensorID FROM TBLXML b where id = 749417;
  end if;
  val:=val+1;
end loop;



Но такая конструкция обрабатывается очень долго, минут 40. В связи с этим вопрос:
Как ускорить?
...
Рейтинг: 0 / 0
15.08.2016, 09:22
    #39291733
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Очень долгий разбор XML
...
Рейтинг: 0 / 0
15.08.2016, 14:22
    #39291982
Fogel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Очень долгий разбор XML
mozgen,

чтобы теория не казалась сухой и была опора для изучения - вот тебе пример на твоих данных:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
with t0 as (select 
xmltype('<root><Results ID="0001">
    <Defect REC_NO="66" Position="3.0500000000000003" Length="0.1" DefectValue="104.87" Class="X" Aggregate="PM" SensorID="20"/>
    <Defect REC_NO="67" Position="4.07" Length="0.1" DefectValue="179.74" Class="X" Aggregate="PM" SensorID="1"/>
    <Defect REC_NO="68" Position="4.07" Length="0.1" DefectValue="149.95000000000002" Class="X" Aggregate="PM" SensorID="2"/>
    <Defect REC_NO="69" Position="4.07" Length="0.1" DefectValue="18.82" Class="X" Aggregate="PM" SensorID="4"/>
    <Defect REC_NO="70" Position="4.07" Length="0.1" DefectValue="74.58" Class="X" Aggregate="PM" SensorID="5"/>
    <Defect REC_NO="71" Position="4.07" Length="0.1" DefectValue="37.34" Class="X" Aggregate="PM" SensorID="13"/>
    <Defect REC_NO="72" Position="4.07" Length="0.1" DefectValue="38.050000000000004" Class="X" Aggregate="PM" SensorID="14"/>
    <Defect REC_NO="73" Position="4.07" Length="0.1" DefectValue="0.11" Class="X" Aggregate="PM" SensorID="17"/>
    <Defect REC_NO="1137" Position="79.725000000000009" Length="0.03" DefectValue="0" Class="E" Aggregate="VS" SensorID="3"/>
    <Defect REC_NO="1138" Position="80.693" Length="0.03" DefectValue="0" Class="P" Aggregate="VS" SensorID="4"/>
</Results>
<Results ID="0002">
    <Defect REC_NO="86" Position="3.0500000000000003" Length="0.1" DefectValue="104.87" Class="X" Aggregate="PM" SensorID="20"/>
    <Defect REC_NO="87" Position="4.07" Length="0.1" DefectValue="179.74" Class="X" Aggregate="PM" SensorID="1"/>
</Results>
</root>') as descript
from dual)
select t1.* from t0, xmltable('//root/Results[@ID="0001"]' passing t0.descript
columns
def_agr_pm xmltype path '/Defect'
) t,
xmltable('//Defect' passing t.def_agr_pm columns
                   def_rec varchar2(50) path '@REC_NO',
                   def_pos varchar2(50) path '@Position',
                   def_len varchar2(50) path '@Length',
                   def_val varchar2(50) path '@DefectValue',
                   def_cl varchar2(50) path '@Class',
                   def_sen varchar2(50) path '@SensorID', 
                   def_agr varchar2(50) path '@Aggregate') t1
                   where t1.def_agr = 'PM';

...
Рейтинг: 0 / 0
16.08.2016, 06:09
    #39292333
mozgen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Очень долгий разбор XML
Fogel,

Спасибо, буду разбираться)
...
Рейтинг: 0 / 0
16.08.2016, 09:25
    #39292374
mozgen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Очень долгий разбор XML
В общих чертах разобрался, переделал вод себя, получилось это:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
with t0 as (SELECT xmltype(cursor(select * from TBLXML where id = NEWID)) DESKRIPTION from dual)
select t1.* from t0, xmltable('//Billet/NDTResults' passing t0.DESKRIPTION columns def_agr_pm xmltype path '//Defect' ) t,
xmltable('//Defect' passing t.def_agr_pm columns
                  DefectPos FLOAT(126) path '@Position',
                  DefectLength FLOAT(100) path '@Length',
                  DefectAmplitude FLOAT(120) path '@DefectValue',
                  DefectClass VARCHAR2(50) path '@Class',
                  SensorID FLOAT(100) path '@SensorID', 
                  agregate varchar2(50) path '@Aggregate') t1
                  where t1.agregate = 'PM';




Но вот нюанс... в Worksheet'е (работаю в SQL Developer) все отрабатывает отлично, но в процедуре ругается на строку
Код: plsql
1.
with t0 as (SELECT xmltype(cursor(select * from TBLXML where id = NEWID)) DESKRIPTION from dual)


с ошибкой
Код: plsql
1.
Error(22,1): PLS-00428: в этом предложении SELECT ожидается фраза INTO


если вставляю INTO, то уже на строку
Код: plsql
1.
select t1.* from t0, xmltable('//Billet/NDTResults' passing t0.DESKRIPTION columns def_agr_pm xmltype path '//Defect' ) t,


с ошибкой
Код: plsql
1.
Error(23,61): PL/SQL: ORA-00904: "T0"."DESKRIPTION": недопустимый идентификатор


да, "DESKRIPTION" написано верно, орфографически конечно нет, но так уж повелось :)
не понимаю как быть, в чем трабл?
...
Рейтинг: 0 / 0
16.08.2016, 10:23
    #39292409
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Очень долгий разбор XML
mozgen
Код: plsql
1.
with t0 as (SELECT xmltype(cursor(select * from TBLXML where id = NEWID)) DESKRIPTION from dual)



А что, посложнее никак нельзя? :)

Код: plsql
1.
2.
3.
4.
5.
select xt.*
from TBLXML t, xmltable('/Results/Defect' passing xmltype(t.DESKRIPTION)
columns...
) xt
where t.id = NEWID


...и таки да, в pl/sql нельзя выполнить просто select - обязательно надо как-то использовать результат.
Либо select into, либо курсорный цикл, либо open for... но это уже совсем другая история, основы pl/sql называется.
...
Рейтинг: 0 / 0
19.08.2016, 14:05
    #39294607
mozgen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Очень долгий разбор XML
andrey_anonymous,
да, согласен, чет тупанул =)

Хотя тупняк продолжается... можете подсказать КАК это сделать? О_о
Че-то я в упор не понимаю как здесь можно данные в массив вставить да и вообще куда здесь цикл лепить...
...
Рейтинг: 0 / 0
19.08.2016, 16:12
    #39294694
Алымов Анатолий
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Очень долгий разбор XML
mozgenandrey_anonymous,
да, согласен, чет тупанул =)

Хотя тупняк продолжается... можете подсказать КАК это сделать? О_о
Че-то я в упор не понимаю как здесь можно данные в массив вставить да и вообще куда здесь цикл лепить...
Всё зависит от того, что с данными надо сделать дальше. Разобрать то xml надо для чего-то.
...
Рейтинг: 0 / 0
22.08.2016, 06:50
    #39295262
mozgen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Очень долгий разбор XML
Алымов Анатолий,

Вытаскиваю значения параметров и вставляю их в таблицу. данные по каждому дефекту пишутся в разные строки (следующий insert).
...
Рейтинг: 0 / 0
22.08.2016, 13:28
    #39295494
Dmitry.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Очень долгий разбор XML
так тебе никакого цикла не надо.

insert into TABLENAME
select ... from XMLTABLE
...
Рейтинг: 0 / 0
13.10.2016, 08:59
    #39325873
mozgen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Очень долгий разбор XML
Разобрался) получилось вот что:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
insert into table1(
(SELECT t1.* 
    FROM 
    XMLTABLE ('/root/NDTResults' 
             PASSING (XMLtemp) -- Здесь использую переменную, в моем случае так оказалось проще.
             COLUMNS
                DefectPos FLOAT(126) path '@Position',
                DefectLength FLOAT(100) path '@Length',
                DefectAmplitude FLOAT(120) path '@DefectValue',
                DefectClass VARCHAR2(50) path '@Class',
                SensorID varchar2(50) path '@SensorID',
                agregate varchar2(50) path '@Aggregate'
             ) t1 where t1.Agregate = 'PM'));   



Но задача усложнилась. Теперь (на самом деле и раньше нужно было) необходимо выбрать элементы из разных частей XML.
Поясню:

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
<Root>
<POData SEQ_ID="1008" ID="752055"/>
<Results ID="0001">
    <Defect REC_NO="66" Position="3.0500000000000003" Length="0.1" DefectValue="104.87" Class="X" Aggregate="PM" SensorID="20"/>
    <Defect REC_NO="67" Position="4.07" Length="0.1" DefectValue="179.74" Class="X" Aggregate="PM" SensorID="1"/>
    <Defect REC_NO="68" Position="4.07" Length="0.1" DefectValue="149.95000000000002" Class="X" Aggregate="PM" SensorID="2"/>
    <Defect REC_NO="69" Position="4.07" Length="0.1" DefectValue="18.82" Class="X" Aggregate="PM" SensorID="4"/>
    <Defect REC_NO="70" Position="4.07" Length="0.1" DefectValue="74.58" Class="X" Aggregate="PM" SensorID="5"/>
    <Defect REC_NO="71" Position="4.07" Length="0.1" DefectValue="37.34" Class="X" Aggregate="PM" SensorID="13"/>
    <Defect REC_NO="72" Position="4.07" Length="0.1" DefectValue="38.050000000000004" Class="X" Aggregate="PM" SensorID="14"/>
    <Defect REC_NO="73" Position="4.07" Length="0.1" DefectValue="0.11" Class="X" Aggregate="PM" SensorID="17"/>
 ...
    <Defect REC_NO="1137" Position="79.725000000000009" Length="0.03" DefectValue="0" Class="E" Aggregate="VS" SensorID="3"/>
    <Defect REC_NO="1138" Position="80.693" Length="0.03" DefectValue="0" Class="P" Aggregate="VS" SensorID="4"/>
</Results>
<Root>



Соответственно при запросе:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
insert into table1(
(SELECT t1.* 
    FROM 
    XMLTABLE ('/root/NDTResults' 
             PASSING (XMLtemp) 
             COLUMNS
                A1 NUMBER PATH 'Root/POData/@ID',
                DefectPos FLOAT(126) path '@Position',
                DefectLength FLOAT(100) path '@Length',
                DefectAmplitude FLOAT(120) path '@DefectValue',
                DefectClass VARCHAR2(50) path '@Class',
                SensorID varchar2(50) path '@SensorID',
                agregate varchar2(50) path '@Aggregate'
             ) t1 where t1.Agregate = 'PM'));   


В A1 логично возвращает NULL
А при запросе
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
insert into table1(
(SELECT t1.* 
    FROM 
    XMLTABLE ('/root' 
             PASSING (XMLtemp) 
             COLUMNS
                A1 NUMBER PATH 'POData/@ID',
                DefectPos FLOAT(126) path 'NDTResults/@Position',
                DefectLength FLOAT(100) path 'NDTResults/@Length',
                DefectAmplitude FLOAT(120) path 'NDTResults/@DefectValue',
                DefectClass VARCHAR2(50) path 'NDTResults/@Class',
                SensorID varchar2(50) path 'NDTResults/@SensorID',
                agregate varchar2(50) path 'NDTResults/@Aggregate'
             ) t1 where t1.Agregate = 'PM'));   


Что еще более логично
Код: plsql
1.
ORA-19279: XPTY0004 - XQuery dynamic type mismatch: expected singleton sequence - got multi-item sequence



Тут нюанс - ID встречается только один раз, т.к. это номер, на которому принадлежит вся последующая последовательность.

В результате должно получиться так:
ID A1 DefectPos DefectLength DefectAmplitude DefectClass SensorID Agregate25654 752055 24.330000000000002 0.1 15021 X 2 PM25655 752055 24.330000000000002 0.1 1848 X 4 PM25656 752055 24.330000000000002 0.1 7463 X 5 PM25657 752055 24.330000000000002 0.1 3756 X 13 PM25658 752055 24.330000000000002 0.1 3775 X 14 PM25659 752055 24.330000000000002 0.1 -01 X 17 PM25660 752055 24.330000000000002 0.1 1109 X 18 PM

И у меня что-то ступор, ребят, подскажите как условие правильно составить, или два разных запроса объединить(?!), или как еще это сделать-то?
...
Рейтинг: 0 / 0
13.10.2016, 09:14
    #39325885
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Очень долгий разбор XML
mozgen
Код: plsql
1.
                A1 NUMBER PATH 'Root/POData/@ID',

Надо понимать, что есть точка отсчёта после XMLTABLE ('/Root/Results/Defect', и куда нужно от неё двигаться:
Код: plsql
1.
                  A1 NUMBER PATH './../../POData/@ID',
...
Рейтинг: 0 / 0
13.10.2016, 10:12
    #39325966
mozgen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Очень долгий разбор XML
Elic,

О! точно, огромное спасибо!) Теперь все встало на свои места))
...
Рейтинг: 0 / 0
30.11.2016, 07:27
    #39357388
mozgen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Очень долгий разбор XML
Господа, решил продолжить тему. Ситуация изменилась в лучшую сторону, сейчас разбор проходит секунд за 30-60, но в результате это тоже очень долго. Как можно еще ускорить?

Мой код:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
MERGE INTO TBL_NDT_PM 
USING
 (
    (SELECT t1.* 
    FROM 
    XMLTABLE ('/Billet/NDTResults/Defect' 
             PASSING (XMLtemp)
             COLUMNS
                PM_ID,
                A1,
                DefectPos FLOAT(126) path '@Position',
                DefectLength FLOAT(100) path '@Length',
                DefectAmplitude FLOAT(120) path '@DefectValue',
                DefectClass VARCHAR2(50) path '@Class',
                SensorID varchar2(50) path '@SensorID',
                agregate varchar2(50) path '@Aggregate',
                R2ID  NUMBER PATH './../../POData/@L3ID'
             ) t1 where t1.Agregate = 'PM'-- and DefectClass = 'RP'
    )
 ) my ON (TBL_NDT_PM.R2 = my.R2ID)
 WHEN MATCHED THEN
  UPDATE SET
    DEFECT_POS = DefectPos,
    DEFECT_LENGTH = DefectLength,
    DEFECT_AMPLITUDE = DefectAmplitude,
    DEFECT_CLASS = DefectClass,
    SENSOR_ID = SensorID,
    AGGREGATE = agregate
  where TBL_NDT_PM.R2=my.R2ID 
 WHEN NOT MATCHED THEN 
	INSERT (TBL_NDT_PM_ID, DEFECT_POS, DEFECT_LENGTH, DEFECT_AMPLITUDE, DEFECT_CLASS, SENSOR_ID, AGGREGATE, R2)
	VALUES (NULL , DefectPos, DefectLength, DefectAmplitude, DefectClass, SensorID, agregate, R2ID);




В среднем, часть XMLины которую пытаюсь разобрать состоит из 1К-1,05К строк, полагаю, что для таких размеров разбор слишком долгий...
...
Рейтинг: 0 / 0
05.12.2016, 10:25
    #39360253
XMLer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Очень долгий разбор XML
mozgen,
поиграйся с XMLTRANSFORM
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Очень долгий разбор XML / 15 сообщений из 15, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]