powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Очень долгий разбор XML
15 сообщений из 15, страница 1 из 1
Очень долгий разбор XML
    #39291731
mozgen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброго времени суток Господа Ораклоиды. Прошу помощи в разборе 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
Очень долгий разбор XML
    #39291733
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Очень долгий разбор XML
    #39291982
Фотография Fogel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Очень долгий разбор XML
    #39292333
mozgen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Fogel,

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

Код: 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
Очень долгий разбор XML
    #39292409
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Очень долгий разбор XML
    #39294607
mozgen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andrey_anonymous,
да, согласен, чет тупанул =)

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

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

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

insert into TABLENAME
select ... from XMLTABLE
...
Рейтинг: 0 / 0
Очень долгий разбор XML
    #39325873
mozgen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Разобрался) получилось вот что:
Код: 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
Очень долгий разбор XML
    #39325885
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mozgen
Код: plsql
1.
                A1 NUMBER PATH 'Root/POData/@ID',

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

О! точно, огромное спасибо!) Теперь все встало на свои места))
...
Рейтинг: 0 / 0
Очень долгий разбор XML
    #39357388
mozgen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Господа, решил продолжить тему. Ситуация изменилась в лучшую сторону, сейчас разбор проходит секунд за 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
Очень долгий разбор XML
    #39360253
XMLer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mozgen,
поиграйся с XMLTRANSFORM
...
Рейтинг: 0 / 0
15 сообщений из 15, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Очень долгий разбор XML
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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