I'm trying to query the following XML the way I always do, but due to its declaration and the empty "NextQuantity" - "NextDate" fields, I'm having troubles querying the XML.
What's the right way to do this?
Thank you.
<StocksResp xmlns="http://xxxxxx" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Stocks>
<Stock>
<Sku>30101.06-L</Sku>
<Quantity>247610</Quantity>
<NextQuantity1>15243</NextQuantity1>
<NextDate1>2019-02-27</NextDate1>
<NextQuantity2 i:nil="true" />
<NextDate2 />
<NextQuantity3 i:nil="true" />
<NextDate3 />
<NextQuantity4 i:nil="true" />
<NextDate4 />
<NextQuantity5 i:nil="true" />
<NextDate5 />
<NextQuantity6 i:nil="true" />
<NextDate6 />
</Stock>
<Stock>
<Sku>30101.06-M</Sku>
<Quantity>241606</Quantity>
<NextQuantity1 i:nil="true" />
<NextDate1 />
<NextQuantity2 i:nil="true" />
<NextDate2 />
<NextQuantity3 i:nil="true" />
<NextDate3 />
<NextQuantity4 i:nil="true" />
<NextDate4 />
<NextQuantity5 i:nil="true" />
<NextDate5 />
<NextQuantity6 i:nil="true" />
<NextDate6 />
</Stock>
</Stocks>
<Count>4837</Count>
<Currency i:nil="true" />
<Language>ES</Language>
<ErrorCode i:nil="true" />
<ErrorMessage i:nil="true" />
</StocksResp>
===============================================
DECLARE #xml XML
SELECT #xml = x.y FROM OPENROWSET (BULK 'file.xml',SINGLE_BLOB) as x(y)
SELECT
x.y.value('Sku[1]','varchar(15)'),
x.y.value('Quantity[1]','int'),
x.y.value('NextDate1[1]','varchar(20)'),
x.y.value('NextQuantity1[1]','int'),
'mr'
FROM #xml.nodes('Stocks/Stock') x(y)
Might this help?
DECLARE #xml XML=
N'<StocksResp xmlns="http://xxxxxx" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Stocks>
<Stock>
<Sku>30101.06-L</Sku>
<Quantity>247610</Quantity>
<NextQuantity1>15243</NextQuantity1>
<NextDate1>2019-02-27</NextDate1>
<NextQuantity2 i:nil="true" />
<NextDate2 />
<NextQuantity3 i:nil="true" />
<NextDate3 />
<NextQuantity4 i:nil="true" />
<NextDate4 />
<NextQuantity5 i:nil="true" />
<NextDate5 />
<NextQuantity6 i:nil="true" />
<NextDate6 />
</Stock>
<Stock>
<Sku>30101.06-M</Sku>
<Quantity>241606</Quantity>
<NextQuantity1 i:nil="true" />
<NextDate1 />
<NextQuantity2 i:nil="true" />
<NextDate2 />
<NextQuantity3 i:nil="true" />
<NextDate3 />
<NextQuantity4 i:nil="true" />
<NextDate4 />
<NextQuantity5 i:nil="true" />
<NextDate5 />
<NextQuantity6 i:nil="true" />
<NextDate6 />
</Stock>
</Stocks>
<Count>4837</Count>
<Currency i:nil="true" />
<Language>ES</Language>
<ErrorCode i:nil="true" />
<ErrorMessage i:nil="true" />
</StocksResp>';
-You need to declare the default namespace. You would not need to declare the namespace i...
WITH XMLNAMESPACES(DEFAULT 'http://xxxxxx','http://www.w3.org/2001/XMLSchema-instance' AS i)
SELECT
#xml.value(N'(/StocksResp/Count/text())[1]',N'int') AS StockResp_Count
,#xml.value(N'(/StocksResp/Currency/text())[1]',N'int') AS StockResp_Currency
,st.value(N'(Sku/text())[1]',N'nvarchar(max)') AS Stock_Sku
,st.value(N'(Quantity/text())[1]',N'int') AS Stock_Quantity
,st.value(N'(NextQuantity1/text())[1]',N'int') AS Stock_NextQuantity1
,st.value(N'(NextDate1/text())[1]',N'date') AS Stock_NextDate1
,st.value(N'(NextQuantity2/text())[1]',N'int') AS Stock_NextQuantity2
,st.value(N'(NextDate2/text())[1]',N'date') AS Stock_NextDate2
,st.value(N'(NextQuantity3/text())[1]',N'int') AS Stock_NextQuantity3
,st.value(N'(NextDate3/text())[1]',N'date') AS Stock_NextDate3
,st.value(N'(NextQuantity4/text())[1]',N'int') AS Stock_NextQuantity4
,st.value(N'(NextDate4/text())[1]',N'date') AS Stock_NextDate4
,st.value(N'(NextQuantity5/text())[1]',N'int') AS Stock_NextQuantity5
,st.value(N'(NextDate5/text())[1]',N'date') AS Stock_NextDate5
,st.value(N'(NextQuantity6/text())[1]',N'int') AS Stock_NextQuantity6
,st.value(N'(NextDate6/text())[1]',N'date') AS Stock_NextDate6
FROM #xml.nodes('/StocksResp/Stocks/Stock') A(st);
Some remarks:
It is a very bad habit to name-number elements (Date1, Date2 and so on). If you can change this, you should use a nested set of elements and number them eiter by their position or with an attribute like
<Next index="1">
<Date>2018-01-01</Date>
<Quantity>1</Quantity>
</Next>
[... more of them ...]
you can see, that I read the just-once values directly from the variable, while the repeating elements are taken from a derived table by .nodes().
Related
I want to update empty XML variable in MSSQL
i try every solutions like replace, outer apply , modify but nothing working
please help me find a solutions
<ArrayOfField xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Field>
<FieldType>1</FieldType>
<DataType>1</DataType>
<Label>department</Label>
<Name>department</Name>
<Description />
<Min />
<Max />
<DefaultValue />
<Required>0</Required>
<SelectItems />
<Formula />
<DataSourceUID xsi:nil="true" />
<TrueText />
<FalseText />
<UnconfirmtyRule xsi:nil="true" />
<UnconfirmtyRequired xsi:nil="true" />
<UnconfirmityFormUID xsi:nil="true" />
<ConfirmationStatus xsi:nil="true" />
<ConfirmationUserBasedType xsi:nil="true" />
<ConfirmationRightUsers />
<Newline>false</Newline>
<ColumnWith>12</ColumnWith>
<Offset>0</Offset>
</Field>
<Field>
<FieldType>1</FieldType>
<DataType>4</DataType>
<Label>Test</Label>
<Name>test</Name>
<Description />
<Min />
<Max />
<DefaultValue />
<Required>0</Required>
<SelectItems />
<Formula />
<TrueText />
<FalseText />
<UnconfirmtyRule xsi:nil="true" />
<UnconfirmtyRequired xsi:nil="true" />
<UnconfirmityFormUID xsi:nil="true" />
<ConfirmationStatus xsi:nil="true" />
<ConfirmationUserBasedType xsi:nil="true" />
<ConfirmationRightUsers />
<Newline>false</Newline>
<ColumnWith>12</ColumnWith>
<Offset>0</Offset>
</Field>
</ArrayOfField>
I want update DefaultValue if DataType = 1
New DefaultValue like <DefaultValue>TODAY()<DefaultValue/>
I try this code but not update anything what is my mistake?
DECLARE #SearchType NVARCHAR(100)=N'1';
DECLARE #ReplaceWith NVARCHAR(100)=N'TODAY()';
UPDATE FormSchema
SET Fields.modify('replace value of
(/ArrayOfField
/Field[DataType=sql:variable("#SearchType")]
/DefaultValue/text())[1]
with sql:variable("#ReplaceWith")')
WHERE Fields.exist('/ArrayOfField
/Field[DataType=sql:variable("#SearchType")]')=1;
You need to use different XML modify operations depending on whether the target element is empty or not (i.e.: it contains no text as opposed to being xsi:nil="true"). For example...
--
-- Setup data...
--
create table dbo.FormSchema (
Fields xml
);
insert dbo.FormSchema (Fields) values
(N'<ArrayOfField>
<Field>
<DataType>1</DataType>
<DefaultValue>Hello, world!</DefaultValue>
</Field>
<Field>
<DataType>2</DataType>
<DefaultValue />
</Field>
</ArrayOfField>'),
(N'<ArrayOfField>
<Field>
<DataType>1</DataType>
<DefaultValue />
</Field>
<Field>
<DataType>3</DataType>
<DefaultValue />
</Field>
</ArrayOfField>');
--
-- Perform updates...
--
DECLARE
#SearchType NVARCHAR(100) = N'1',
#ReplaceWith NVARCHAR(100) = N'TODAY()';
UPDATE dbo.FormSchema
SET Fields.modify('
replace value of (/ArrayOfField/Field[DataType=sql:variable("#SearchType")]/DefaultValue/text())[1]
with sql:variable("#ReplaceWith")
')
WHERE Fields.exist('(/ArrayOfField/Field[DataType=sql:variable("#SearchType")]/DefaultValue/text())[1]')=1;
UPDATE dbo.FormSchema
SET Fields.modify('
insert text{sql:variable("#ReplaceWith")}
into (/ArrayOfField/Field[DataType=sql:variable("#SearchType")]/DefaultValue)[1]
')
WHERE Fields.exist('(/ArrayOfField/Field[DataType=sql:variable("#SearchType")]/DefaultValue)[1]')=1
AND Fields.exist('(/ArrayOfField/Field[DataType=sql:variable("#SearchType")]/DefaultValue/text())[1]')=0;
--
-- Check results...
--
SELECT * FROM dbo.FormSchema;
Which yields the results:
Fields
<ArrayOfField><Field><DataType>1</DataType><DefaultValue>TODAY()</DefaultValue></Field><Field><DataType>2</DataType><DefaultValue /></Field></ArrayOfField>
<ArrayOfField><Field><DataType>1</DataType><DefaultValue>TODAY()</DefaultValue></Field><Field><DataType>3</DataType><DefaultValue /></Field></ArrayOfField>
I have the below XML:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetBatchResponse xmlns="https://webservices.aba.com/">
<web:GetBatchResult xmlns:web="https://webservices.aba.com/">
<web:Loco>
<web:LocoType>
<web:Errors />
<web:Pos />
<web:Ref />
<web:Episode>
<web:EpisodeType>
<web:EpisodeId>1</web:EpisodeId>
<web:StartTime>2021-02-01T01:41:58</web:StartTime>
<web:EpisodeDataAtStart>
<web:Name>Sam</web:Name>
<web:Height>5.10</web:Height>
<web:Age>26</web:Age>
<web:Salary />
</web:EpisodeDataAtStart>
<web:EpisodeDataAtEnd>
<web:Grade>C</web:Grade>
<web:Salary>500</web:Salary>
</web:EpisodeDataAtEnd>
</web:EpisodeType>
</web:Episode>
<web:EmpUnit>21</web:EmpUnit>
<web:EmpOrg>XE</web:EmpOrg>
</web:LocoType>
<web:LocoType>
<web:Errors />
<web:Pos />
<web:Ref />
<web:Episode>
<web:EpisodeType>
<web:EpisodeId>2</web:EpisodeId>
<web:StartTime>2021-02-02T01:41:58</web:StartTime>
<web:EpisodeDataAtStart>
<web:Name>Emma</web:Name>
<web:Height>5.5</web:Height>
<web:Age>23</web:Age>
<web:Salary />
</web:EpisodeDataAtStart>
<web:EpisodeDataAtEnd>
<web:Grade>B</web:Grade>
<web:Salary>550</web:Salary>
</web:EpisodeDataAtEnd>
</web:EpisodeType>
</web:Episode>
<web:EmpUnit>17</web:EmpUnit>
<web:EmpOrg>XE</web:EmpOrg>
</web:LocoType>
</web:Loco>
<web:EndTimeUTC xsi:nil="true" />
</web:GetBatchResult>
</GetBatchResponse>
</soap:Body>
</soap:Envelope>
This is not a valid xml, just a replica created by me. Please ignore any typing mistakes, if found.
I'm able to extract the data from the 1st and the last node, i.e., I'm able to get EpisodeId, StartTime, EmpUnit and EmpOrg using the below query:
DECLARE #xml XML = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetBatchResponse xmlns="https://webservices.aba.com/">
<web:GetBatchResult xmlns:web="https://webservices.aba.com/">
<web:Loco>
<web:LocoType>
<web:Errors />
<web:Pos />
<web:Ref />
<web:Episode>
<web:EpisodeType>
<web:EpisodeId>1</web:EpisodeId>
<web:StartTime>2021-02-01T01:41:58</web:StartTime>
<web:EpisodeDataAtStart>
<web:Name>Sam</web:Name>
<web:Height>5.10</web:Height>
<web:Age>26</web:Age>
<web:Salary />
</web:EpisodeDataAtStart>
<web:EpisodeDataAtEnd>
<web:Grade>C</web:Grade>
<web:Salary>500</web:Salary>
</web:EpisodeDataAtEnd>
</web:EpisodeType>
</web:Episode>
<web:EmpUnit>21</web:EmpUnit>
<web:EmpOrg>XE</web:EmpOrg>
</web:LocoType>
<web:LocoType>
<web:Errors />
<web:Pos />
<web:Ref />
<web:Episode>
<web:EpisodeType>
<web:EpisodeId>2</web:EpisodeId>
<web:StartTime>2021-02-02T01:41:58</web:StartTime>
<web:EpisodeDataAtStart>
<web:Name>Emma</web:Name>
<web:Height>5.5</web:Height>
<web:Age>23</web:Age>
<web:Salary />
</web:EpisodeDataAtStart>
<web:EpisodeDataAtEnd>
<web:Grade>B</web:Grade>
<web:Salary>550</web:Salary>
</web:EpisodeDataAtEnd>
</web:EpisodeType>
</web:Episode>
<web:EmpUnit>17</web:EmpUnit>
<web:EmpOrg>XE</web:EmpOrg>
</web:LocoType>
</web:Loco>
<web:EndTimeUTC xsi:nil="true" />
</web:GetBatchResult>
</GetBatchResponse>
</soap:Body>
</soap:Envelope>'
WITH XMLNAMESPACES (DEFAULT 'https://webservices.aba.com/', 'http://schemas.xmlsoap.org/soap/envelope/' AS soap, 'https://webservices.aba.com/' AS web)
SELECT
P.PT.value('(./web:EpisodeId/text())[1]','INT') AS INT,
P.PT.value('(./web:StartTime/text())[1]','DATETIME') AS StartTime,
L.LT.value('(./web:EmpUnit/text())[1]','int') AS EmpUnit,
L.LT.value('(./web:EmpOrg/text())[1]','char(2)') AS EmpOrg
FROM #XML.nodes('soap:Envelope/soap:Body/GetBatchResponse/web:GetBatchReult/web:Loco/web:LocoType') L(LT)
CROSS APPLY L.LT.nodes('web:Episode/web:EpisodeType')P(PT);
I also need the values for Name, Height, Age, SalaryAtStart, Grade and SalaryAtEnd
Need some help. Thanks in advance.
I have this xml data in my table as you can see :
<ArrayOfFlowDetailParameters xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<FlowDetailParameters>
<DepartmentId>23</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>22</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>7</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>18</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
</ArrayOfFlowDetailParameters>
when i want to find the departmentid with value=22 my query returns 0 result but when i search value=23 it returns 1 result i think it is because of [1].
declare #departmentId nvarchar(max)
set #departmentId=22
select Requests.* from Requests
where
and (FlowDetailParameter.value('(/ArrayOfFlowDetailParameters/FlowDetailParameters/DepartmentId/text())[1]','bigint') = #departmentId )
It sounds like you're trying to query a list of requests where the FlowDetailParameter column's XML contains a record where the DepartmentId matches your #departmentId variable, right?
The [1] in your query specifies to only check the first occurrence of DepartmentId in each row's FlowDetailParameter XML. You won't get a match unless the first DepartmentId in the XML matches your parameter.
Instead, you can use the following query to find all requests that have a FlowDetailParameter matching the #departmentid variable using the nodes() method.
SELECT r.*
FROM #Requests r
WHERE EXISTS (SELECT *
FROM r.FlowDetailParameter.nodes('/ArrayOfFlowDetailParameters/FlowDetailParameters/DepartmentId') as Parms(DepartmentId)
WHERE DepartmentId.value('.', 'bigint') = #departmentid)
I've never worked with XML before but have been tasked to import a document into a SQL Server table. As a test, I'm been using an example I found online and, for now, I'm only trying to retrieve a single column:
DECLARE #X XML
SELECT #X=MC2016
FROM OPENROWSET (BULK 'C:\TEMP\Detail_2016.xml', SINGLE_BLOB) AS MEDPOP_2016(MC2016)
DECLARE #hdoc int
EXEC SP_XML_PREPAREDOCUMENT #hdoc OUTPUT, #X
select *
from openxml (#hdoc, '/Results/Record', 1)
with (
MemberID varchar(10)
)
EXEC SP_XML_REMOVEDOCUMENT #hdoc
When I execute this in SSMS, the query completes but I get zero rows of output even though I know that there are many thousands of records.
I'm running SQL Server 2016. The XML file is too large include here but here's the first record (deidentified):
<?xml version="1.0" encoding="utf-8"?>
<Results xmlns="http://www.dxcg.com/Results.xsd">
<Record MemberID="0012345" DOB="1917-09-09" Age="100" Gender="M" Child="0" Elderly="1" Male="1" AgeGender="34" NoHCC="false" NoValid="false" NoDiag="false" NoRxGroup="true" NoValidRx="false" ELG1="12" ELIGF1="1" ECAT="-1" MCAID="0" OREC="0" EXP1="33.78" ExpRx1="0.00">
<Groups>
<Group Name="FSC" Value="99" />
</Groups>
<Period Name="Base">
<Classifier Type="Standard">
<DxGs>
<DxG ID="887" />
<DxG ID="638" />
<DxG ID="910" />
<DxG ID="911" />
<DxG ID="716" />
<DxG ID="534" />
<DxG ID="530" />
<DxG ID="61" />
</DxGs>
<CCs>
<CC ID="266" HierarchyY1="true" HierarchyY2="true" />
<CC ID="230" HierarchyY1="true" HierarchyY2="true" />
<CC ID="19" HierarchyY1="true" HierarchyY2="true" />
<CC ID="349" HierarchyY1="false" HierarchyY2="true" />
<CC ID="231" HierarchyY1="false" HierarchyY2="false" />
<CC ID="347" HierarchyY1="true" HierarchyY2="false" />
<CC ID="293" HierarchyY1="true" HierarchyY2="true" />
</CCs>
<RCCs>
<RCC ID="77" HierarchyY1="true" HierarchyY2="true" />
<RCC ID="62" HierarchyY1="true" HierarchyY2="true" />
<RCC ID="2" HierarchyY1="true" HierarchyY2="true" />
<RCC ID="103" HierarchyY1="true" HierarchyY2="true" />
<RCC ID="87" HierarchyY1="true" HierarchyY2="true" />
</RCCs>
<ACCs>
<ACC ID="19" HierarchyY1="true" HierarchyY2="true" />
<ACC ID="16" HierarchyY1="true" HierarchyY2="true" />
<ACC ID="2" HierarchyY1="true" HierarchyY2="true" />
<ACC ID="27" HierarchyY1="true" HierarchyY2="true" />
<ACC ID="22" HierarchyY1="true" HierarchyY2="true" />
</ACCs>
<RxGs />
<ARxGs />
</Classifier>
</Period>
<DCGs>
<DCG ID="2" Value="0.5" />
</DCGs>
<ADCGs>
<ADCG ID="2" Value="0.5" />
</ADCGs>
<Preds>
<Pred ID="122" Value="1.6393262810427782" />
<Pred ID="2" Value="0.55220631651432173">
<RiskDriver Label="" HCC="293" Contribution="68.537299593489152" />
<RiskDriver Label="" HCC="230" Contribution="18.964637260918547" />
<RiskDriver Label="" HCC="347" Contribution="5.12631266098848" />
<RiskDriver Label="" HCC="266" Contribution="4.43513850335468" />
<RiskDriver Label="" HCC="19" Contribution="2.936611981249146" />
</Pred>
</Preds>
</Record>
Ultimately, I want to load this entire record into a table but as of now, I can't even read a single column and I'm not getting any error messages to point me in a direction to look.
What am I missing here? Thanks.
Best regards,
Corey
Starting from the code from the link provided in the comments you can use this code:
DECLARE #X XML
SELECT #X=MC2016
FROM OPENROWSET (BULK 'c:\TEMP\Detail_2016.xml', SINGLE_BLOB) AS MEDPOP_2016(MC2016)
DECLARE #hdoc int
EXEC SP_XML_PREPAREDOCUMENT #hdoc OUTPUT, #X, '<myNs xmlns:ns1="http://www.dxcg.com/Results.xsd"/>'
;WITH XMLNAMESPACES ('http://www.dxcg.com/Results.xsd' as ns1)
select *
from openxml (#hdoc, '/ns1:Results/ns1:Record', 1)
with (
MemberID varchar(10)
)
Results:
Note: the xml you posted is probably missing a the closing tag for root element </Results>
I'm trying to implement factorial in the xml language of xcerion.
<step id="fac">
<alias name="p" value="={$n}*{$p}" />
<alias name="n" value="={$n}-1" />
<operation name="decision">
<when test="'{$n}'>'0'" step="fac" />
</operation>
</step>
<alias name="p" value="1" />
<alias name="n" value="4" />
<operation name="call" value="fac" />
My code works, but I think it's a bit wordy.
How does this language compare with other xml languages?
Especially handling of variables, selection, loops and subroutine calling.