I have a table of people which build from two columns the first one is id and the second one is XML which counties the person details.
For example the person XML file can be:
<Person>
<name>First Last</name>
<address>5 Champ de Mars</address>
<city>Paris</city>
<country>France</country>
<phone-number>+3312345</phone-number>
</Person>
I would like to know how I can extract the value of each one of the parameters in the XML using regexp_substr, I have tried to use the function EXTRACTVALUE which caused me too many problems.
I am ruining oracle.
For example if querying the XML I gave:
select regexp_substr(XML_file, 'pattern name') from peoples where id = 1;
will result in: First Last.
Thank you in advance
Yonatan
What kind of problems did you run into with EXTRACTVALUE?
Because it seems to be what you need...
Something along the lines of SELECT EXTRACTVALUE(my_xml_column, '/Person/name') FROM my_table WHERE id=; should return 'First Last' as asked...
Related
I'm a beginner when it comes to SQL and have no experience with XML so I'm after a little bit of help.
At the moment I am looking at a single table and just using the query below
select
name,
convert(xml, convert(varbinary(max), orders)) ClientOrders
from client;
In the second columns of SQL output, I have a very lengthy bit of XML similar to the example below. I've used "..." just to skip over some of the output and give a general idea.
Name
ClientOrders
Client1
<report ... ><QueryParameter></QueryParameter Name = "#hello1"><commandtext> ...<value>Example1</value>....<value>Example2</value>...<value>Example3</value>...</commandtext></report>
Client2
<report ... ><QueryParameter></QueryParameter Name = "#hello2"><commandtext> ...<value>Example4</value>....<value>Example5</value>...<value>Example6</value>...</commandtext></report>
I have this for a lot of rows and this output is so long that it exceeds the Excel cell character limit. I'm only looking for the values Example1 through to Example6 in the example given above. Is there an SQL command I can run to get the above string between the open and close value?
I am using SSMS version 18.9.1
Cheers
I am just trying to pull the records bypassing the XML path in where the condition of SQL unfortunately I am unable to do.
Note: Pull the records bypassing input as salesteamid value. Please someone can help me to run the query without any failures.
Query :
SELECT * from activity where= ExtractValue('/ActivityId/Agent/Territory/SalesTeamId[contains(10669)]');
XML:
<Activity
xmlns="urn:astrazeneca:na:Activity:domain:3" RestrictionGroup="NONE"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="DiscussionActivityType" TransactionCode="I" CreatedOnDate="2019-11-21T16:04:29" UpdatedOnDate="2019-11-21T16:04:32" SourceCreatedByID="20303090" SourceCreatedByFirstName="Brandy" SourceCreatedByLastName="Nirider" SourceCreatedByRole="" SourceUpdatedByID="20303090" SourceUpdatedByFirstName="Brandy" SourceUpdatedByLastName="Nirider" SourceSystemCode="FSA" SystemOfRecordCode="FSA" RecordCompanyCode="AZN" SourceCountry="USA" SourceRegion="USA" SourceSystemGroup="VNA" SystemOfRecordGroup="VNA">
<ActivityId>
<ns2:ID
xmlns:ns2="urn:astrazeneca:na:CommonTypes:domain:2" SystemCode="VNA">a080P00001YZM7WQAX
</ns2:ID>
</ActivityId>
<Agent>
<EmployeeId>
<ns2:ID
xmlns:ns2="urn:astrazeneca:na:CommonTypes:domain:2" SystemCode="EMPLID">20303090
</ns2:ID>
</EmployeeId>
<Territory>
<ns2:TerritoryId
xmlns:ns2="urn:astrazeneca:na:CommonTypes:domain:2">
<ns2:ID SystemCode="AZ">20070009</ns2:ID>
</ns2:TerritoryId>
<ns2:TerritoryCode
xmlns:ns2="urn:astrazeneca:na:CommonTypes:domain:2">20070009
</ns2:TerritoryCode>
<ns2:Role
xmlns:ns2="urn:astrazeneca:na:CommonTypes:domain:2">PSS
</ns2:Role>
<ns2:Description
xmlns:ns2="urn:astrazeneca:na:CommonTypes:domain:2">Indianapolis C IN 2
</ns2:Description>
<ns2:SalesTeamId
xmlns:ns2="urn:astrazeneca:na:CommonTypes:domain:2">
<ns2:ID SystemCode="AZ">10669</ns2:ID>
</ns2:SalesTeamId>
<ns2:SalesTeamCode
xmlns:ns2="urn:astrazeneca:na:CommonTypes:domain:2">D_ALPHA
</ns2:SalesTeamCode>
</Territory>
</Agent>
<Customer>
<AZCustomerMasterID SystemCode="AZ">58586509</AZCustomerMasterID>
<SourceCustomerID SystemCode="NAVVA">001U000000pMTySIAW</SourceCustomerID>
<CustomerType>HCP</CustomerType>
<CustomerActivityRole>participant</CustomerActivityRole>
</Customer>
<ReferenceContent>
<ReferenceName>Reported Adverse Reaction</ReferenceName>
<ReferenceType>action</ReferenceType>
<ReferenceId SystemCode="VNA">Reported Adverse Reaction</ReferenceId>
</ReferenceContent>
<StartDate>2019-11-21T16:03:00</StartDate>
<EndDate>2019-11-21T16:03:00</EndDate>
<Topic>
<Name>BYDUREON BCISE</Name>
<Product>
<AZBrandId SystemCode="AZ">881574</AZBrandId>
<AZProductId SystemCode="AZ">881574</AZProductId>
<SourceProductId SystemCode=""/>
<ReferenceProductId SystemCode=""/>
<ProductName>BYDUREON BCISE</ProductName>
</Product>
</Topic>
<ActivityAction>discussion</ActivityAction>
<ActivityStatus>completed</ActivityStatus>
<ActivityInitiatedBy>AstraZeneca agent</ActivityInitiatedBy>
<ActivityOutcome>success with identified customer</ActivityOutcome>
<CommunicationMode>in person</CommunicationMode>
<LocationSetting>Selling</LocationSetting>
<SourceValues>
<Status>Submitted</Status>
<SubStatus>Completed</SubStatus>
<Applet>Actions</Applet>
<Activity>Detail Only</Activity>
<InteractionCategory>A_Selling (PSS)</InteractionCategory>
<Type>Selling</Type>
</SourceValues>
<Priority>2</Priority>
<DiscussionTool>N</DiscussionTool>
<ActivityTypeCheck>DiscussionActivityType</ActivityTypeCheck>
</Activity>
Assuming you're trying to filter on an ID within the XML, you have an issue with syntax, you've supplied the root node as ActivityId instead of Activity, you aren't going down to the ID node, you're misusing contains - and that probably isn't what you want anyway; and you're ignoring the namespaces.
This will only find rows where the XML has a specific ID:
SELECT * from activity
where ExtractValue(xml,
'/Activity/Agent/Territory/ns2:SalesTeamId/ns2:ID/text()',
'xmlns="urn:astrazeneca:na:Activity:domain:3" xmlns:ns2="urn:astrazeneca:na:CommonTypes:domain:2"'
) = 10669;
But ExtractValue has long been deprecated, so you should use XMLQuery instead. Or in this context it would probably make more sense to use XMLExists, with the value you want embeded:
SELECT * from activity
where XMLExists('
declare default element namespace "urn:astrazeneca:na:Activity:domain:3";
declare namespace ns2="urn:astrazeneca:na:CommonTypes:domain:2";
/Activity/Agent/Territory/ns2:SalesTeamId/ns2:ID[text()=10669]
'
passing xml
);
or perhaps more usefully supplied as an argument:
SELECT * from activity
where XMLExists('
declare default element namespace "urn:astrazeneca:na:Activity:domain:3";
declare namespace ns2="urn:astrazeneca:na:CommonTypes:domain:2";
/Activity/Agent/Territory/ns2:SalesTeamId/ns2:ID[text()=$id]
'
passing xml, 10669 as "id"
);
db<>fiddle
If you then want to extract specific data from the XML in matching rows then look at XMLQuery or XMLTable - but that's a separate issue.
I encounter some problems that i don't understand with APEX.... Well, let's be specific.
I ve got a select element retrieving a top 50 of most liked url (P11_URL). This is populate by a table view, TOp_Domains.
I create an element called "Context" that have to print all text containing the URL selected by the user from the element select. Those Texts come from another table, let's say "twitter_post".
I create a dynamic action (show only) with this sql/statement:
Select TXT, NB_RT, RANK
from myschema.twitter_post
where TXT like '%:P11_URL%'
group by TXT, NB_RT, RANK
.... and it doesn't work... I think APEX don't like like clause... But i don't know how to do. Let's keep in min an url could have been shared by multiple Tweets, that's why this element "context" is important for me.
I tried to bypass the problem by building a State (in french Statique) and a dynamic action that will refresh the state but it doesn't work neither... bouhououououou
TriX
Right click on the 'P11_URL' and create DA. Event :change, Item:P11_URL. As the true action of the DA, select 'Set Value'. Write your query in the sql stmt area. In the page items to submit, select 'P11_URL' . In the 'Affected Items': select 'Context'.
Query should be :
Select TXT, NB_RT, RANK
from myschema.twitter_post
where TXT like '%' || :P11_URL || '%'
group by TXT, NB_RT, RANK
So
Thanks to #Madona... Their example made me realised my mistake. I wrote the answer here for futher help if somebody encouter the same porblem.
A list select element get as arguments a display value (the one you want to be shown in your screen.... if you want so....^^ ) and a return value (in order, I think to linked dynamic actions). So to solved my problem i had to shape my sql statement as:
select hashtags d, hastags r
from my table
order by 1
[let s say that now in Apex it s an object called P1_HASHTAGS]
First step problem solving.
In fact, the ranking as second value, as i put into my sql statement was making some mitsakens into my 'Where like' clause search... well... Newbie am i!
Second step was to correctly formate the sql statement receiving the datas from my select lov (P1_HASHTAGS) into my interactive report. As shown here:
Select Id, hashtags
from my table
where txt like '%'||:P1_HASHTAGS||'%'
And it works!
Thank you Madona your example helped me figure my mistakes!
I have an xml like the below.
<LPNDetail>
<ItemName>5054807025389</ItemName>
<DistroNbr/>
<DistributionNbr>TR001000002514</DistributionNbr>
<OrderLine>2</OrderLine>
<RefField2/>
<RefField3>OU01180705</RefField3>
<RefField4>0002</RefField4>
<RefField5>Retail</RefField5>
<Qty>4</Qty>
<QtyUom>Unit</QtyUom>
</LPNDetail>
<LPNDetail>
<ItemName>5054807025563</ItemName>
<DistroNbr/>
<DistributionNbr>TR001000002514</DistributionNbr>
<OrderLine>4</OrderLine>
<RefField2/>
<RefField3>OU01180705</RefField3>
<RefField4>0004</RefField4>
<RefField5>Retail</RefField5>
<Qty>2</Qty>
<QtyUom>Unit</QtyUom>
</LPNDetail>
I have extracted the xml field using extract.xmltype and now i am getting the below result.
42
But i need to sum the quantity values i.e i need to get result as 6 (4+2).
Any help will be appreciated.
Thanks,
Shihaj
It is not clear what you mean by "an xml". If it's supposed to be an XML document, you are missing the outermost tags, perhaps something like <Document> ..... </Document>
If your text value is EXACTLY as you have shown it (which would be pretty bad), you can wrap within such outermost tags manually, and then use standard Oracle XML tools. For the illustration below I assume you simply have a string (VARCHAR2 or CLOB), not converted to XML type; in that case, I concatenate the beginning and end tags, and then convert to XMLtype, in the query.
with t ( str ) as (
select '<LPNDetail>
<ItemName>5054807025389</ItemName>
<DistroNbr/>
<DistributionNbr>TR001000002514</DistributionNbr>
<OrderLine>2</OrderLine>
<RefField2/>
<RefField3>OU01180705</RefField3>
<RefField4>0002</RefField4>
<RefField5>Retail</RefField5>
<Qty>4</Qty>
<QtyUom>Unit</QtyUom>
</LPNDetail>
<LPNDetail>
<ItemName>5054807025563</ItemName>
<DistroNbr/>
<DistributionNbr>TR001000002514</DistributionNbr>
<OrderLine>4</OrderLine>
<RefField2/>
<RefField3>OU01180705</RefField3>
<RefField4>0004</RefField4>
<RefField5>Retail</RefField5>
<Qty>2</Qty>
<QtyUom>Unit</QtyUom>
</LPNDetail>'
from dual
)
-- End of SIMULATED table (for testing purposes only, not part of the solution)
-- Query begins below this line
select sum(x.qty) as total_quantity
from t,
xmltable('/Document/LPNDetail'
passing xmltype('<Document>' || t.str || '</Document>')
columns qty number path 'Qty') x
;
Output:
TOTAL_QUANTITY
--------------
6
I'm looking for a db2 function that does a text contain search. At present I am running the following query against the data below....
SELECT distinct
s.search_id,
s.search_heading,
s.search_url
FROM repman.search s, repman.search_tags st
WHERE s.search_id = st.search_id
AND ( UPPER(s.search_heading) LIKE (cast('%REPORT%' AS VARGRAPHIC(32)))
OR (UPPER(st.search_tag) LIKE cast('%REPORT%' AS VARGRAPHIC(32)))
)
ORDER BY s.search_heading;
Which returns...
But if I change the search text to %REPORTS% rather than %REPORT% (which I need to do) the like search does not work and I get zero results.
I read a link that used a function named CONTAINS like below but when trying to use the function I get an error.
SELECT distinct
s.search_id,
s.search_heading,
s.search_url
FROM repman.search s, repman.search_tags st
WHERE s.search_id = st.search_id
AND CONTAINS(s.search_heading, 'REPORTS') = 1
Has anynoe got any suggestions? I'm on db2 version DB2/LINUXPPC 9.1.6.
Thanks
In order to look for a pattern in a string, you can use Regular Expressions. They are built-in DB2 with xQuery since DB2 v9. There are also other ways to do that. I wrote an article in my blog (in Spanish that you can translate) about Regular Expressions in DB2.
xmlcast(xmlquery('fn:matches(\$TEXT,''^[A-Za-z 0-9]*$'')')