Import danych z XML

0

Witam,

stworzyłem xml w którym mam 10 rekordów.
Gdy odpalę:

-- Tworzenie tabeli KONTA_AD

create table KONTA_AD (
	nr number(3),
	imie varchar2(15),
	nazwisko varchar2(30),
	login varchar2(30),
	typ varchar2(30),
	dzial varchar2(30),
	email varchar2(30),
	data_nadania date,
	nr_upowaznienia varchar2(13)
	);

-- Import danych z pliku XML (import.xml)

DECLARE
pliczek xmltype := xmltype( bfilename('PLIKI_XML','import.xml'), nls_charset_id('AL32UTF8') );
z_nr number(3);	
z_imie varchar2(15);
	z_nazwisko varchar2(30);
	z_login varchar2(30);
	z_typ varchar2(30);
	z_dzial varchar2(30);
	z_email varchar2(30);
	z_data_nadania date;
	z_nr_upowaznienia varchar2(13);
BEGIN
 select zrodlo.nr into z_nr
 from xmltable(
  '/KONTA_AD/user'
  passing pliczek
  columns nr varchar2(15) path 'nr'
 ) zrodlo;
 select zrodlo.imie into z_imie
 from xmltable(
  '/KONTA_AD/user'
  passing pliczek
  columns imie varchar2(15) path 'imie'
 ) zrodlo;
 select zrodlo.nazwisko into z_nazwisko
 from xmltable(
  '/KONTA_AD/user'
  passing pliczek
  columns nazwisko varchar2(30) path 'nazwisko'
 ) zrodlo;
select zrodlo.login into z_login
 from xmltable(
  '/KONTA_AD/user'
  passing pliczek
  columns login varchar2(30) path 'login'
 ) zrodlo;
select zrodlo.typ into z_typ
 from xmltable(
  '/KONTA_AD/user'
  passing pliczek
  columns typ varchar2(30) path 'typ'
 ) zrodlo;
select zrodlo.dzial into z_dzial
 from xmltable(
  '/KONTA_AD/user'
  passing pliczek
  columns dzial varchar2(30) path 'dzial'
 ) zrodlo;
select zrodlo.email into z_email
 from xmltable(
  '/KONTA_AD/user'
  passing pliczek
  columns email varchar2(30) path 'email'
 ) zrodlo;
select zrodlo.data_nadania into z_data_nadania
 from xmltable(
  '/KONTA_AD/user'
  passing pliczek
  columns data_nadania varchar2(30) path 'data_nadania'
 ) zrodlo;
select zrodlo.nr_upowaznienia into z_nr_upowaznienia
 from xmltable(
  '/KONTA_AD/user'
  passing pliczek
  columns nr_upowaznienia varchar2(30) path 'nr_upowaznienia'
 ) zrodlo;
   insert into KONTA_AD (nr,imie,nazwisko,login,typ,dzial,email,data_nadania,nr_upowaznienia)
  values (z_nr,z_imie,z_nazwisko,z_login,z_typ,z_dzial,z_email,z_data_nadania,z_nr_upowaznienia);
END;

otrzymuje bład:
Error report:
ORA-01422: dokładne pobranie zwraca większą liczbę wierszy niż zamówiono
ORA-06512: przy linia 13
01422. 00000 - "exact fetch returns more than requested number of rows"
*Cause: The number specified in exact fetch is less than the rows returned.
*Action: Rewrite the query or change number of rows requested

Jeśli w pliku XML z którego importuje jest tylko jeden rekord to dane importują się.
Linia 13 to:

select zrodlo.nr into z_nr
0

no ale dziwi Cię to? Przecież próbujesz wczytać wszystkie wartości z pola np. /KONTA_AD/user/nr do jednej zmiennej. Masz to po prostu źle napisane. Tu masz przykład: https://community.oracle.com/thread/2182669 lub http://www.gokhanatil.com/2016/08/how-to-import-data-to-oracle-rdbms-from-xml.html

0

Zmieniłem na:

BEGIN

INSERT INTO KONTA_AD (nr,imie,nazwisko,login,typ,dzial,email,data_nadania,nr_upowaznienia)

WITH t AS (SELECT xmltype(bfilename('PLIKI_XML','import.xml'), nls_charset_id('AL32UTF8')) xmlcol FROM dual)

SELECT
extractValue(value(x),'/KONTA_AD/user') nr,
extractValue(value(x),'/KONTA_AD/user') imie,
extractValue(value(x),'/KONTA_AD/user') nazwisko,
extractValue(value(x),'/KONTA_AD/user') login,
extractValue(value(x),'/KONTA_AD/user') typ,
extractValue(value(x),'/KONTA_AD/user') dzial,
extractValue(value(x),'/KONTA_AD/user') email,
extractValue(value(x),'/KONTA_AD/user') data_nadania,
extractValue(value(x),'/KONTA_AD/user') nr_upowaznienia
FROM t,TABLE(XMLSequence(extract(t.xmlcol,'/KONTA_AD/user'))) x;
END;

ale wstawia we wszystkie pola null.

Nazwa tabeli do której importuje to KONTA_AD, a plik z którego importuje to import.xml

0

nie możesz zrobić tak jak w linku, który Ci podałem?

select x1.status_code, 
        x1.status_remarks,
        x2.segment_number, 
        x2.remarks
 from xmltable(
  '/ACCOUNT_HEADER_ACK/HEADER'
  passing acct_doc
  columns header_no      for ordinality,
          status_code    number        path 'STATUS_CODE',
          status_remarks varchar2(100) path 'STATUS_REMARKS'
 )
0
DECLARE

 acct_doc xmltype := xmltype( bfilename('KONTA_AD','import.xml'), nls_charset_id('AL32UTF8') );

BEGIN

 insert into xxrp_acct_details (nr,imie,nazwisko,login,typ,dzial,email,data_nadania,nr_upowaznienia)
 select x1.nr 
        x1.imie,
        x2.nazwisko, 
        x2.login,
x3. typ,
x3.dzial,
x4.email,
x4.data_nadania,
x5.nr_upowaznienia
 from xmltable(
  '/KONTA_AD/user'
  passing acct_doc
  columns header_no      for ordinality,
          nr    number        path 'nr',
          imie varchar2(20) path 'imie',
          nazwisko varchar2(30) path 'nazwisko',
          login varchar2(30) path 'login',
          typ varchar2(20) path 'typ',
          dzial varchar2(20) path 'dzial',
          data_nadania varchar2(20) path 'data_nadania',
          nr_upowaznienia varchar2(20) path 'nr_upowaznienia'
 ) x1,
 xmltable(
  '$d/KONTA_AD/user[$hn]/DETAIL'
  passing acct_doc as "d",
          x1.header_no as "hn"
  columns nr number        path 'nr',
          imie        varchar2(100) path 'imie'
 ) x2
 ;


Zanim dopisze kolejen pola to czy ok?

0

no nie dobrze:

  1. masz tabele x3, x4, x5? Pole login masz w tabeli x2 czy x1?
  2. w pierwszym poście nic nie było o /KONTA_AD/user[$hn]/DETAIL pewny jesteś, że też ma być?
    Generalnie widać, że nie bardzo wiesz co robisz. Przecież to
select x1.nr 
        x1.imie,
        x2.nazwisko, 
        x2.login,
x3. typ,
x3.dzial,
x4.email,
x4.data_nadania,
x5.nr_upowaznienia
 from xmltable(
  '/KONTA_AD/user'
  passing acct_doc
  columns header_no      for ordinality,
          nr    number        path 'nr',
          imie varchar2(20) path 'imie',
          nazwisko varchar2(30) path 'nazwisko',
          login varchar2(30) path 'login',
          typ varchar2(20) path 'typ',
          dzial varchar2(20) path 'dzial',
          data_nadania varchar2(20) path 'data_nadania',
          nr_upowaznienia varchar2(20) path 'nr_upowaznienia'
 ) x1

jest najnormalniejszy w świecie select tylko nie z tabeli a z XMLa. A reszta to już nic innego jak insert z selecta. To są przecież podstawy (poza znalezieniem jak zrobić select z XMLa a nie z tabeli ale to masz)

0

Poradziłem sobie już z importem i eksportem, ale mam dwa problemy:

  1. Przy eksporcie do pliku używam:
spool /home/oracle/Desktop/PLIKI_XML/test.xml;

które umieszczone jest przed select... i wtedy do pliku oprócz wyniku wrzuca mi treść zapytania select.

Treść select:

SELECT XMLELEMENT ("USER",
                   XMLELEMENT ("IMIE", IMIE),
                   XMLELEMENT ("NAZWISKO", NAZWISKO),
                   XMLELEMENT ("DZIAL", DZIAL),
		   XMLELEMENT ("LOGIN", LOGIN),
                   XMLELEMENT ("TYP", TYP),
  		   XMLELEMENT ("EMAIL", EMAIL),
		   XMLELEMENT ("DATA_NADANIA", DATA_NADANIA),
XMLELEMENT ("DATA_COFNIECIA", DATA_COFNIECIA)
) AS KONTA_AD
FROM KONTA_AD JOIN UPOWAZNIENIA ON
(KONTA_AD.NR_UPOWAZNIENIA=UPOWAZNIENIA.NR_UPOWAZNIENIA)
WHERE TYP='UZYTKOWNIK DOMENY'
ORDER BY NAZWISKO;
  1. W pliku brak
<?xml version="1.0" ?>

reszta jest OK

1 użytkowników online, w tym zalogowanych: 0, gości: 1