How to insert XML attributes in oracle tables using XMLTABLE Type - sql

Please help to resolve the issue.
I verified previous questions in the same blog but could not able to resolve the issue.
SELECT x.* --,--XXAR_CUST_ACCT_INT_TBL_S.nextval
FROM XMLTABLE ('for $i in $wh//NewCustomerToEBS,
$j in $i//SiteLine
$j in $i//ContactLine
return <deNormalizedWH>{$i}{$j}</deNormalizedWH>'
PASSING xmltype (y)
AS "wh"
COLUMNS ATTRIBUTE2 VARCHAR2(20) path NewCustomerToEBS/#AccessoryFulfilmentOrg',
CUSTOMER_TYPE_SITE VARCHAR2(80) path 'SiteLine/#AccountType',
CUSTOMER_NUMBER_CONTACT VARCHAR2(40) path 'ContactLine/#AccountNumber') x.
when I try to execute the select statement in my custom procedure, I am getting below error:
This is my complete xml file, but for reference I gave 3 columns (each from header, line and contact).
DECLARE
P_XML_DATA CLOB;
BEGIN
P_XML_DATA := '<NewCustomersToEBS> <NewCustomerToEBS AccessoryFulfilmentOrg="TEST" AccountType="TEST1" AlternateEmail="syad#tek.com" BlindShippments="NHGSV" Classification="HXHB" ComplianceCustomer="SKBCS" CustomerCategory="IUYT" CustomerNumber="FGGD12" CustomerProspectCode="LKOU" CustomerType="LOUTR" EDISDQSegmentCustomer="LOUY" Email="HDEG" Fax="HHBGG" FreeOnBoardPoint="KJHTR" FreightTerms="LKJ" OrderType="HBHJBJ" OrganizationName="VEN" Phone="LKJU87" PriceList="knjj" ProfileClass="MJRFS" RequestDataType="JNCJA" RoutingWindow="OIJH" SalesChannel="MNJH" ShipSet="RDSA" ShippingWindow="LKOP" StoreLocations="EDCG" UPCLabletype="LKJUO" URLs="JXABHCBH"> <SiteLine AccountType="JHFJS" AlternateEmailAddress="SV" BillToAddressLine1="SVSF" BillToAddressLine2="HGG" BillToAddressLine3="DBH" BillToCity="BJKD" BillToCountry="BB" BillToPostalCode="2323" BillToProvinice="BD" BillToState="GSDG" CensusRegion="DH" Country="HH" CustomerProspectCode="43T" CustomerType="HFHF" ECSRetailStoreLocation="FHF" EDILocation="HFHF" Email="FHF" Fax="5656" FreeOnBoardPoint="NFN" FreightTerms="BC" OrderType="KKMCK" Phone="4756" ProfileClass="KBD" Region="LS" ResidentialAddress="SS" SalesPerson="SW" ShipMethod="BDGD" ShipToAddressLine1="RF" ShipToAddressLine2="ES" ShipToAddressLine3="SS" ShipToCity="FF" ShipToCountry="GG" ShipToPostalCode="76" ShipToProvince="MM" ShipToState="GG" SiteLocation="GGG" SiteNumber="977" StoreLocations="GKV" StoresDistributionCentre="RT" URLs="RRR"/> <SiteLine AccountType="LOKI" AlternateEmailAddress="JJS" BillToAddressLine1="KMKK" BillToAddressLine2="POKJ" BillToAddressLine3="KIJO" BillToCity="PL" BillToCountry="OKJ" BillToPostalCode="OU" BillToProvinice="PL" BillToState="MN" CensusRegion="NB" Country="JH" CustomerProspectCode="KH" CustomerType="LK" ECSRetailStoreLocation="MJ" EDILocation="CF" Email="GF" Fax="987" FreeOnBoardPoint="MN" FreightTerms="LG" OrderType="UY" Phone="23" ProfileClass="LE" Region="DE" ResidentialAddress="ER" SalesPerson="RT" ShipMethod="TY" ShipToAddressLine1="YU" ShipToAddressLine2="IU" ShipToAddressLine3="SD" ShipToCity="DF" ShipToCountry="FG" ShipToPostalCode="34" ShipToProvince="NH" ShipToState="HG" SiteLocation="JK" SiteNumber="98" StoreLocations="YT" StoresDistributionCentre="RE" URLs="EW"/> <ContactLine AccountNumber="123" Acknowledgement="GGG" Email="NB" FaxAreaCode="54" FaxNumber="456" FaxType="BB" FirstName="KJ" Invoices="HG" JobTitle="FD" LastName="DS" OrganizationName="VG" PhoneAreaCode="66" PhoneNumber="55" PhoneType="XX" ShipTo="XX"/><ContactLine AccountNumber="345" Acknowledgement="RT" Email="TT" FaxAreaCode="33" FaxNumber="22" FaxType="BC" FirstName="SS" Invoices="JH" JobTitle="HH" LastName="JJ" OrganizationName="JHG" PhoneAreaCode="57" PhoneNumber="99" PhoneType="90" ShipTo="MM"/> </NewCustomerToEBS></NewCustomersToEBS>';
XXAR_CUSTOMER_INBOUND_PROC(P_XML_DATA);
commit;
END;
ORA-19114: XPST0003 - error during parsing the XQuery expression:
LPX-00801: XQuery syntax error at 'j'
3 $j in $i//ContactLine
- ^
ORA-06512: at "APPS.XXAR_CUSTOMER_INBOUND_PROC", line 8
ORA-06512: at line 13
Please review the error message and let me know where i am doing mistake.
Thanks in advance!!

You need a , after $j in $i//SiteLine - this is the cause for the error.
But you also used $j twice (which might work but give wrong results).
Try:
SELECT x.*
FROM XMLTABLE ('for $i in $wh//NewCustomerToEBS,
$j in $i//SiteLine,
$z in $i//ContactLine
return <deNormalizedWH>{$i}{$j}{$z}</deNormalizedWH>'
PASSING xmltype (y)
AS "wh"
COLUMNS ATTRIBUTE2 VARCHAR2(20) path 'NewCustomerToEBS/#AccessoryFulfilmentOrg',
CUSTOMER_TYPE_SITE VARCHAR2(80) path 'SiteLine/#AccountType',
CUSTOMER_NUMBER_CONTACT VARCHAR2(40) path 'ContactLine/#AccountNumber') x
Here is a sqlfiddle demo

Related

XMLQuery with Oracle

I'm doing examples from workbook. I created table and insert couple of records. Below is my code:
Create table:
CREATE TABLE test_Pracownicy
(IDPracownika NUMBER(3),
Dane XMLTYPE);
Insert record to the table:
INSERT INTO test_Pracownicy (IDPracownika, Dane)
VALUES (1,
XMLTYPE('
<PRecord>
<Nazwisko>Kowalski</Nazwisko>
<Imie>Jan</Imie>
<RokUrodz>1980</RokUrodz>
<Wzrost>1.77</Wzrost>
<DataZatr>2001/02/10</DataZatr>
</PRecord>')
);
Now I want to run XMLQuery:
SELECT IDPracownika,
XMLQuery(
'FOR $i IN /PRecord
WHERE $i /Nazwisko = "Kowalski"
ORDER BY $i/Imie
RETURN $i'
PASSING by VALUE Dane
RETURNING CONTENT) NazwiskoXML
FROM test_Pracownicy;
and I'm getting error:
ORA-19114: XPST0003 - error during parsing the XQuery expression:
LPX-00801: XQuery syntax error at 'i'
1 FOR $i IN /PRecord
- ^
19114. 00000 - "error during parsing the XQuery expression: %s"
*Cause: An error occurred during the parsing of the XQuery expression.
*Action: Check the detailed error message for the possible causes.
Error at Line: 117 Column: 6
I changed query to small (for, where, return...) letters and it's workging:
SELECT IDPracownika,
XMLQuery(
'for $i in /PRecord
where$i /Nazwisko = "Kowalski"
order by $i /Imie
retrun $i'
PASSING by VALUE Dane
RETURNING CONTENT) NazwiskoXML
FROM test_Pracownicy;
It's case sensitive.

How to pass value in xmltable

How can I pass a variable value inside the xpath of xmltable?
DECLARE
v NUMBER := 0;
BEGIN
SELECT *
FROM xml_billrun_files t ,
xmltable('/invoice/AR_ITEMS[#elem='||v||']/ITEMS/USAGE_RECORDS/SESSION_INFO'
passing t.update_xmldoc
columns chrg_duration VARCHAR2(20) path 'DURATION',
amount NUMBER path 'AMOUNT') x;
END;
I've tried this one.
DECLARE
v NUMBER := 0;
BEGIN
SELECT *
FROM xml_billrun_files t ,
xmltable('/invoice/AR_ITEMS[#elem=$i]/ITEMS/USAGE_RECORDS/SESSION_INFO'
passing t.update_xmldoc, xmltype(v) as "i"
columns chrg_duration VARCHAR2(20) path 'DURATION',
amount NUMBER path 'AMOUNT') x;
END;
But it returns an error:
ORA-31011: XML parsing failed
ORA-19202: Error occurred in XML processing
LPX-00210: expected '<' instead of '0'
Error at line 1
ORA-06512: at "SYS.XMLTYPE", line 310
ORA-06512: at line 1
ORA-06512: at line 5
31011. 00000 - "XML parsing failed"
*Cause: XML parser returned an error while trying to parse the document.
*Action: Check if the document to be parsed is valid.
thanks for the help.
In my answer to your previous question, I incorrectly used xmltype(lp) as "lp" for your XMLQuery call. Not sure why it didn't complain there, but it didn't actually restrict the match anyway...
For this XMLTable call you can pass the number directly, without conversion/cast, as it's already a number:
SELECT chrg_duration, amount
into ...
FROM xml_billrun_files t ,
xmltable('/invoice/AR_ITEMS[#elem=$i]/ITEMS/USAGE_RECORDS/SESSION_INFO'
passing t.update_xmldoc, v as "i"
columns chrg_duration VARCHAR2(20) path 'DURATION',
amount NUMBER path 'AMOUNT') x;
If you're doing it in a for loop, then the index is the wrong data type, and you need to cast it to number:
SELECT chrg_duration, amount
into ...
FROM xml_billrun_files t ,
xmltable('/invoice/AR_ITEMS[#elem=$i]/ITEMS/USAGE_RECORDS/SESSION_INFO'
passing t.update_xmldoc, cast(v as number) as "i"
columns chrg_duration VARCHAR2(20) path 'DURATION',
amount NUMBER path 'AMOUNT') x;

Export all The extended ASCII codes (character code 128-255) in XML file from oracle store procedure

I have created a Store Procedure to generate an xml file of Table Data,
but in my database some table have "extended ASCII codes (character code 128-255)".
When I generate xml file then it shows error "ORA-31061: XDB error: special char to escaped char conversion failed."
So I replaced these Char to space but I need all ASCII codes (character code 128-255) in XML files.
Please help
My Store Procedure is below:
create or replace
PROCEDURE Export_project6
(
V_TABLE_NAME1 IN varchar2,
v_FLAG OUT NUMBER
)
AS
BEGIN
----- Export table data
DECLARE
v_file UTL_FILE.file_type;
qryCtx DBMS_XMLGEN.ctxHandle;
result CLOB;
v_FILENAME varchar2(50);
V_TABLE_NAME varchar2(50);
xt_data xmltype;
v_ctx dbms_xmlgen.ctxHandle;
rc_data sys_refcursor;
BEGIN
V_TABLE_NAME := UPPER(V_TABLE_NAME1) ;
v_file := UTL_FILE.fopen('MYXML',V_TABLE_NAME||'.xml', 'W');
OPEN rc_data FOR
'select * FROM '||V_TABLE_NAME||' ORDER BY 1' ;
v_ctx := dbms_xmlgen.newContext (rc_data);
DBMS_XMLGEN.USEITEMTAGSFORCOLL (v_ctx);
DBMS_XMLGEN.SETNULLHANDLING(v_ctx, 1);
DBMS_XMLGEN.setrowsettag(v_ctx,'root');
DBMS_XMLGEN.setrowtag(v_ctx,V_TABLE_NAME );
result:= DBMS_XMLGEN.getXML(v_ctx);
result := REPLACE( result, '<?xml version="1.0"?>','<?xml version="1.0" encoding="UTF-8" standalone ="yes"?>');
-- DBMS_XMLGEN.RESTARTQUERY (v_ctx);
-- xt_data := dbms_xmlgen.getXMLType (v_ctx);
dbms_xslprocessor.clob2file( result, 'MYXML', ''||V_TABLE_NAME||'.xml',1);
dbms_xmlgen.closeContext (v_ctx);
v_FLAG := 1;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
DBMS_XMLGEN.closeContext (v_ctx);
v_FLAG := 0;
END ;
Please Advices and help here
END Export_project6;
At least part of the problem is that you're specifying the file should be US7ASCII, which only allows the first 128 ASCII characters, not the extended values from 128-255. You're doing that in this line:
dbms_xslprocessor.clob2file( result, 'MYXML', ''||V_TABLE_NAME||'.xml',1);
You're passing 1 as the fourth parameter, csid. That value represents US7ASCII:
SQL> select nls_charset_name(1) from dual;
NLS_CHAR
--------
US7ASCII
Your XML is UTF-8, but specifying that with encoding="UTF-8" has no bearing on how the file is written. Any unrecognised characters are replaced with ?. So you might want to use the same setting for the file:
SQL> select nls_charset_id('UTF8') from dual;
NLS_CHARSET_ID('UTF8')
----------------------
871
So:
dbms_xslprocessor.clob2file( result, 'MYXML', ''||V_TABLE_NAME||'.xml',871);
or to be clearer:
dbms_xslprocessor.clob2file( result, 'MYXML', ''||V_TABLE_NAME||'.xml',
nls_charset_id('UTF8'));
But leaving it as the default might be OK - by not specifying csid at all, or by explicitly setting it to zero - depending on our database environment.
You mentioned you avoid ORA-31061 error if you "replace all ASCIICHAR (0-30) like ♂ : 11 ♀ : 12 ♫ : 14 ☼ : 15 ► : 16 ◄ : 17 ↕ : 18 ‼ : 19 ¶ : 20". Those symbols aren't what you'd expect from ASCII, so your character set or client or something seems to be interpreting them differently.
I get the error with all the ASCII control characters, 0 through to 31, except the printable ones: 9, 10 or 13. But that's what's expected, the other characters in that range are not valid in XML 1.0:
U+0009, U+000A, U+000D: these are the only C0 controls accepted in XML 1.0;
The same page shows that more, but still not all, control characters are allowed in XML 1.1, but as far as I'm aware Oracle only supports 1.0. If you do really have control characters in your data you'll need to strip them (retaining tabs, new lines and carriage returns); the rest would be meaningless in the final XML anyway, and perhaps of limited use in your existing data. I'm not sure if this is real data, or if you'd generated those values as a test.

How to Convert Output of listagg() function into XMLTYPE

I have one stored Procedure P_FP_GET_PATTERN.I expect output in following format
PATTERN_ID |PATTERN_NAME | SHIFT
1 Pattern 1 A,B,C,B,A
2 Pattern 2 C,B,A,C
I'm getting this output in SYS_REFCURSOR ALL_RESULT_SET.I need to pass it in XML format.But the moment i put that output in ALL_RESULT_SET_XML which is my out parameter of stored procedure of XMLTYPE using ALL_RESULT_SET_XML:= XMLTYPE(ALL_RESULT_SET);
Im getting an error as
Error encountered: ORA-31061: XDB error: special char to escaped char conversion failed.
I`m getting this error due to column shown using LISTAGG() function.Anybody can please tell me how to handle this ?
My stored Procedure
create or replace
PROCEDURE P_FP_GET_PATTERN
(
ALL_RESULT_SET_XML OUT XMLTYPE,
P_MESSAGE_ALL OUT VARCHAR2
)
AS
V_ERROR VARCHAR2(2000);
ALL_RESULT_SET SYS_REFCURSOR;
BEGIN
OPEN ALL_RESULT_SET FOR
SELECT PM.PATTERN_ID ,PM.PATTERN_NAME,
LISTAGG(SM.SHIFT_NUMBER) WITHIN GROUP (ORDER BY PD.INSTANCE_DAY) "SHIFT"
FROM T_FP_PATTERN_MASTER PM,
T_FP_PATTERN_DETAILS PD,
T_FP_SHIFT_MASTER SM
WHERE SM.SHIFT_ID= PD.SHIFT_ID
AND PM.PATTERN_ID = PD.PATTERN_ID
GROUP BY PM.PATTERN_NAME,PM.PATTERN_ID;
--Adding output in XML output parameter
ALL_RESULT_SET_XML:= XMLTYPE(ALL_RESULT_SET);
EXCEPTION
WHEN OTHERS
THEN
V_ERROR := SUBSTR(SQLERRM,1,1000);
P_MESSAGE_ALL := 'Error encountered: '||V_ERROR ;
END;

Why am I getting PLS - 00382?

Here is my object def:
CREATE OR REPLACE TYPE FALCON.contacts AS OBJECT (phone VARCHAR2(50)
,phoneusage VARCHAR2(25)
,phonetype VARCHAR2(25)
,email VARCHAR2(150)
,phoneext VARCHAR2(25)
,anytext VARCHAR2(250))
Here is the table def:
CREATE OR REPLACE TYPE FALCON.contacttbl AS TABLE OF contacts
Here is my pipelined function
FUNCTION get_pcontacts(p_conttbl IN xmltypedefs_spec.conttbl)
RETURN falcon.contacttbl
PIPELINED
IS
l_contact falcon.contacts;
BEGIN
FOR n IN 1 .. p_conttbl.count
LOOP
PIPE ROW(**falcon.contacts**(p_conttbl(n).phone, p_conttbl(n).phoneusage, p_conttbl(n).phonetype, p_conttbl(n).email, p_conttbl(n).phoneext, p_conttbl(n).anytext));
END LOOP;
RETURN;
END get_pcontacts;
I am getting the error when I call the table function here:
FUNCTION get_pidxml(p_pidrec xmltypedefs_spec.pidtyp)
RETURN CLOB
IS
l_tmprec CLOB;
l_pxml xmltype;
l_bxml xmltype;
l_pcontacts xmltypedefs_spec.conttbl := p_pidrec.personalcont;
l_bcontacts xmltypedefs_spec.conttbl := p_pidrec.businesscont;
BEGIN
-- l_pxml := get_contacts(p_pidrec, 'p');
-- l_bxml := get_contacts(p_pidrec, 'b');
SELECT xmlelement("pid"
,xmlforest(p_pidrec.setid AS "setID"
,p_pidrec.patidexternal AS "patientIDExternal"
,p_pidrec.patientid AS "patientID"
,p_pidrec.patintasgnauth AS "patientIDInterAssignAuthority"
,p_pidrec.patinttypecd AS "patientIDInternalIDTypeCode"
,p_pidrec.patidalternate1 AS "patientIDAlernate1"
,p_pidrec.patlastname AS "patientLastName"
,p_pidrec.patfirstname AS "patientFirstName"
,p_pidrec.patmiddleinit AS "patientMiddleInitial"
,p_pidrec.patsuffix AS "patientSuffix"
,p_pidrec.patprefix AS "patientPrefix"
,p_pidrec.degree AS "degree"
,p_pidrec.familyname AS "familyName"
,p_pidrec.givenname AS "givenName"
,p_pidrec.mothermaidname AS "mothersMaidenName"
,p_pidrec.dob AS "dateOfBirth"
,p_pidrec.adminsex AS "administrativeSex"
,p_pidrec.patientalias AS "patientAlias"
,p_pidrec.race AS "race"
,p_pidrec.racetext AS "raceText"
,p_pidrec.pataddr1 AS "patientAddress1"
,p_pidrec.pataddr2 AS "patientAddress2"
,p_pidrec.patcity AS "patientCity"
,p_pidrec.patstate AS "patientState"
,p_pidrec.patzip AS "patientZip"
,p_pidrec.countrycode AS "countryCode"
,p_pidrec.addresstype AS "addressType"
,p_pidrec.othgeodesig AS "otherGeographicDesignation"
,p_pidrec.county AS "county"
,(SELECT xmlagg(xmlelement("contactInfo",
xmlforest(phone AS "phoneNumber",
phoneusage AS "telecomUseCode",
phonetype AS "telecomequiptype",
email AS "email",
phoneext AS "phonenumberextension",
anytext AS "anytext")))
FROM TABLE(**get_pcontacts(l_pcontacts**))) AS "personalContact"
http://pls-00382.ora-code.com/
PLS-00382: expression is of wrong type
Since I don't know how xmltypedefs_spec.conttbl is defined, I removed the input parameter from the pipelined function and just had it generate fake data on the fly:
CREATE OR REPLACE FUNCTION get_contacts
RETURN contacttbl PIPELINED
IS
-- converts some structure to pipe of contacts
BEGIN
FOR n IN 1 .. 5 LOOP
PIPE ROW(
contact(
'877-867-5309',
'Work',
'Cell',
'jenny#gmail.com',
n,
'WTF?'
)
);
END LOOP;
RETURN;
END get_contacts;
The subquery now executes without error:
SELECT
xmlagg(
xmlelement("contactInfo",
xmlforest(
phone AS "phoneNumber",
phoneusage AS "telecomUseCode",
phonetype AS "telecomequiptype",
email AS "email",
phoneext AS "phonenumberextension",
anytext AS "anytext"
)
)
)
FROM
TABLE( get_contacts( ) )
This tells me there is probably something wrong with xmltypedefs_spec.conttbl, perhaps in using a collection type within an SQL statement? Not sure. What if you changed xmltypedefs_spec.pidtyp to use the falcon.contacttbl instead of xmltypedefs_spec.conttbl. Seems like you've got one package type and one object type that are doing the same thing?
xmltypedefs_spec defines record types that correspond to XML elements. These record types are used to shred and build XML. Originally, the XML did not use repeating elements, but now must. I am attempting to take a table of xmltypedefs_spec.pidtyp and use the pipelined function to return 'rows' of data from an associative table. It is in this fashion that I want to send rows of array records to build xml.