Table XML de la base de données Oracle vers Oracle: problèmes rencontrés
Question
J'ai un exemple de fichier XML créé à l'aide de Editplus (sous Windows).
< ?xml version="1.0" encoding="UTF-8" ?> < badges > < row UserId="3714" Name="Teacher" Date="2008-09-15T08:55:03.923"/> < row UserId="994" Name="Teacher" Date="2008-09-15T08:55:03.957"/> < / badges>
Mon objectif ici est d’obtenir ces informations dans la table de base de données Oracle. Comme suggéré ici, https://stackoverflow.com/questions/998055?sort=newest#sort-top, j'ai essayé d'exécuter les commandes SQL. Mais n'a pas réussi,
======================== sql query 1 ================== =========
SQL> SELECT XMLTYPE(bfilename('D', 'tmp.xml'), nls_charset_id('UTF8')) xml_data FROM dual;
XML_DATA
------------------------------------------------------------
<?xml version="1.0" encoding="WINDOWS-1252"?>
<badges>
<row UserId="3714" Name
Dans la sortie, je vois que la moitié du fichier XML a été tronquée. Et le type de codage en sortie est vu sous le nom WINDOWS-1252. Quelqu'un pourrait-il expliquer pourquoi cela se passe-t-il ainsi?
============================================ =============================
=============================== sql query 2 ============= ====================
SQL> SELECT UserId, Name, to_timestamp(dt, 'YYYY-MM-DD"T"HH24:MI:SS.FF3') dt
2 FROM (SELECT XMLTYPE(bfilename('D', 'tmp.xml'), 3 nls_charset_id('WINDOWS-1252')) xml_data 4 FROM dual), 5 XMLTable('for $i in /badges/row 6 return $i' 7 passing xml_data 8 columns UserId NUMBER path '@UserId', 9 Name VARCHAR2(50) path '@Name', 10 dt VARCHAR2(25) path '@Date');XMLTable('for $i in /badges/row * ERROR at line 5: ORA-00933: SQL command not properly ended
============================================ ======================= La même requête fonctionnait ici https://stackoverflow.com/questions/998055?sort=newest#sort- en haut . Mais pour moi ce n'est pas le cas. Oracle 10g est installé sur ma machine. Quelqu'un pourrait-il suggérer des corrections pour que les requêtes fonctionnent?
Merci.
La solution
Considérant votre premier point, votre sortie est seulement tronquée à l’affichage. Vous pouvez modifier le nombre d'octets affichés dans SQL * Plus avec SET LONG
:
SQL> SELECT XMLTYPE(bfilename('D', 'test.xml'),
2 nls_charset_id('WINDOWS-1252')) xml_data FROM dual;
XML_DATA
--------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<badges>
<row UserId="3714" Name=
SQL> SET LONG 4000
SQL> /
XML_DATA
--------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<badges>
<row UserId="3714" Name="Teacher" Date="2008-09-15T08:55:03.923"/>
<row UserId="994" Name="Teacher" Date="2008-09-15T08:55:03.957"/>
</badges>
Comme vous l'avez remarqué, votre jeu de caractères sera modifié en fonction des paramètres de votre session NLS (i-e: le fichier sera traduit en jeu de caractères de votre client).
Pour le deuxième point:
- Quelle version de SQL * Plus utilisez-vous? Il est peut-être plus ancien que la base de données et ne reconnaît pas le synthax
- pouvez-vous publier la requête exacte telle que vous l'avez saisie dans SQL * Plus (veuillez utiliser la fonction CODE de SO)
car je ne peux pas reproduire avec Oracle 10.2.0.3:
SQL> SELECT UserId, NAME, to_timestamp(dt, 'YYYY-MM-DD"T"HH24:MI:SS.FF3') dt
2 FROM (SELECT XMLTYPE(bfilename('D', 'test.xml'),
3 nls_charset_id('WINDOWS-1252')) xml_data FROM dual),
4 XMLTable('for $i in /badges/row
5 return $i'
6 passing xml_data columns UserId NUMBER path '@UserId',
7 NAME VARCHAR2(50) path '@Name',
8 dt VARCHAR2(25) path '@Date');
USERID NAME DT
---------- --------- ----------------------------
3714 Teacher 15/09/08 08:55:03,923000000
994 Teacher 15/09/08 08:55:03,957000000
Mise à jour: Cette synthax XMLTable doit être une nouvelle fonctionnalité de la version 10gR2 (10.2. *) (doit être confirmée)
Vous pouvez toutefois utiliser une autre méthode d’accès aux données XML (décrite dans un autre SO ):
SQL> SELECT extractvalue(column_value, '/row/@UserId') "userID",
2 extractvalue(column_value, '/row/@Name') "Name",
3 extractvalue(column_value, '/row/@Date') "Date"
4 FROM TABLE(XMLSequence(XMLTYPE(bfilename('D', 'tmp.xml'),
5 nls_charset_id('WINDOWS-1252')).extract('/badges/row'))) t;
userID Name Date
------- --------- ------------------------
3718 Teacher 2008-09-15T08:55:03.923
994 Teacher 2008-09-15T08:55:03.957
Autres conseils
J'ai eu exactement le même problème, je me demandais pourquoi:
encoding="UTF-8"
remplacé par
encoding="WINDOWS-1250"
dans mon cas (après le chargement).
Ensuite, j'ai compris ce que fait Oracle ici: il convertit le xml encodé en utf-8 en jeu de caractères par défaut de votre base de données, afin de pouvoir le stocker. C'est pourquoi cela change la valeur de 'encoding'. Si le jeu de caractères par défaut de votre base de données est utf-8, l'option 'encodig' ne changera pas.
Si votre xml contient des caractères encodés en utf-8, essayez de le charger dans la base de données avec nls_charset_id ('WINDOWS-1252')
provoquera une erreur.
Donc, pour résumer: vous ne devriez pas vous soucier de encoding = "UTF-8"
en encoding = "WINDOWS-1252", ignorez-le. - la base de données fait son travail.
Merci pour l'aide. 'set Long 4000' corrige le problème de troncature.
Mais je lutte toujours pour que la deuxième requête soit exécutée. Ma version de sqlplus est "SQL * Plus: Version 10.1.0.2.0". Pensez-vous que cette version est la question.
Voici le code que j'ai essayé.
SQL> select xmltype(bfilename('D','tmp.xml'),nls_charset_id('WINDOWS-1252')) xml_data from dual;
XML_DATA
-----------------------------------------------
<?xml version="1.0" encoding="WINDOWS-1252"?>
<badges>
<row UserId="3714" Name
SQL> set LONG 4000
SQL> /
XML_DATA
--------------------------------------------------
<?xml version="1.0" encoding="WINDOWS-1252"?>
<badges>
<row UserId="3714" Name="Teacher" Date="2008-09-15T08:55:03.923"/>
<row UserId="994" Name="Teacher" Date="2008-09-15T08:55:03.957"/>
</badges>
SQL> SELECT UserId, NAME, to_timestamp(dt, 'YYYY-MM-DD"T"HH24:MI:SS.FF3') dt
2 FROM (SELECT XMLTYPE(bfilename('D', 'tmp.xml'),
3 nls_charset_id('WINDOWS-1252')) xml_data FROM dual),
4 XMLTable('for $i in /badges/row
5 return $i'
6 passing xml_data columns UserId NUMBER path '@UserId',
7 NAME VARCHAR2(50) path '@Name',
8 dt VARCHAR2(25) path '@Date');
XMLTable('for $i in /badges/row
*
ERROR at line 4:
ORA-00933: SQL command not properly ended