我需要在tsql中解析以下XML
问题出在哪里。只有第一条记录在where条件中得到验证。如果我将GLNominalAccount值更改为[2],则验证第二个节点。有没有办法可以使用where条件遍历所有节点。我只查找与整个节点中的where条件匹配的GLNominalAccount值。感谢
<JournalEntry xmlns="http://schema.mycompany.com/Info/2"
<JELine sequence="1">
<Amount currencyID="USD">-100.000</Amount>
<FunctionalAmount currencyID="USD">-100.000</FunctionalAmount>
<ReportingCurrencyAmount currencyID="USD">100.000</ReportingCurrencyAmount>
<GLAccount>
<GLNominalAccount>1005690</GLNominalAccount>
<AccountingChartReference>
<ID accountingEntity="T00">T00</ID>
</AccountingChartReference>
</GLAccount>
</JELine>
<JELine sequence="2">
<Amount currencyID="USD">100.000</Amount>
<FunctionalAmount currencyID="USD">100.000</FunctionalAmount>
<ReportingCurrencyAmount currencyID="USD">100.000</ReportingCurrencyAmount>
<GLAccount>
<GLNominalAccount>34180050</GLNominalAccount>
<AccountingChartReference>
<ID accountingEntity="T00">T00</ID>
</AccountingChartReference>
</GLAccount>
</JELine>
</JournalEntry>
下面是我的tsql代码
WITH XMLNAMESPACES(DEFAULT 'http://schema.mycompany.com/Info/2')
SELECT ParamValues.SSD.value('GLNominalAccount[1]', 'varchar(8)')
FROM @xmlData.nodes('//JournalEntry/JELine/GLAccount') AS ParamValues(SSD)
WHERE @xmldata.value(N'(/JournalEntry/JELine/GLAccount/GLNominalAccount)[1]' ,'varchar(max)') LIKE '2%'
OR @xmldata.value('(//JournalEntry/JELine/GLAccount/GLNominalAccount)[1]' , 'varchar(8)') LIKE '3%'
OR @xmldata.value('(//JournalEntry/JELine/GLAccount/GLNominalAccount)[1]' , 'varchar(8)') LIKE '4%'
OR @xmldata.value('(//JournalEntry/JELine/GLAccount/GLNominalAccount)[1]' , 'varchar(8)') LIKE '6%'
OR @xmldata.value('(//JournalEntry/JELine/GLAccount/GLNominalAccount)[1]' , 'varchar(8)') LIKE '7%'
OR @xmldata.value('(//JournalEntry/JELine/GLAccount/GLNominalAccount)[1]' , 'varchar(8)') LIKE '8%'
答案 0 :(得分:0)
顺便说一句:您的示例XML缺少结束>
...
无需循环或迭代。 .nodes()
- 函数将所有同级节点作为行返回:
试试这样:
DECLARE @xml XML=
'<JournalEntry xmlns="http://schema.mycompany.com/Info/2">
<JELine sequence="1">
<Amount currencyID="USD">-100.000</Amount>
<FunctionalAmount currencyID="USD">-100.000</FunctionalAmount>
<ReportingCurrencyAmount currencyID="USD">100.000</ReportingCurrencyAmount>
<GLAccount>
<GLNominalAccount>1005690</GLNominalAccount>
<AccountingChartReference>
<ID accountingEntity="T00">T00</ID>
</AccountingChartReference>
</GLAccount>
</JELine>
<JELine sequence="2">
<Amount currencyID="USD">100.000</Amount>
<FunctionalAmount currencyID="USD">100.000</FunctionalAmount>
<ReportingCurrencyAmount currencyID="USD">100.000</ReportingCurrencyAmount>
<GLAccount>
<GLNominalAccount>34180050</GLNominalAccount>
<AccountingChartReference>
<ID accountingEntity="T00">T00</ID>
</AccountingChartReference>
</GLAccount>
</JELine>
</JournalEntry>';
- 查询
WITH XMLNAMESPACES(DEFAULT 'http://schema.mycompany.com/Info/2')
SELECT j.value('@sequence','int') AS JELine_Sequence
,j.value('(Amount/@currencyID)[1]','nvarchar(max)') AS Amount_CurrencyID
,j.value('(Amount)[1]','decimal(14,4)') AS Amount
,j.value('(FunctionalAmount/@currencyID)[1]','nvarchar(max)') AS FunctionalAmount_CurrencyID
,j.value('(FunctionalAmount)[1]','decimal(14,4)') AS FunctionalAmount
,j.value('(ReportingCurrencyAmount/@currencyID)[1]','nvarchar(max)') AS ReportingCurrencyAmount_CurrencyID
,j.value('(ReportingCurrencyAmount)[1]','decimal(14,4)') AS ReportingCurrencyAmount
,j.value('(GLAccount/GLNominalAccount)[1]','bigint') AS GLNominalAccount
,j.value('(GLAccount/AccountingChartReference/ID/@accountingEntity)[1]','nvarchar(max)') AS accountingEntity
,j.value('(GLAccount/AccountingChartReference/ID)[1]','nvarchar(max)') AS AccountID
FROM @xml.nodes('JournalEntry/JELine') AS A(j)
结果
+-----------------+-------------------+-----------+-----------------------------+------------------+------------------------------------+-------------------------+------------------+------------------+-----------+
| JELine_Sequence | Amount_CurrencyID | Amount | FunctionalAmount_CurrencyID | FunctionalAmount | ReportingCurrencyAmount_CurrencyID | ReportingCurrencyAmount | GLNominalAccount | accountingEntity | AccountID |
+-----------------+-------------------+-----------+-----------------------------+------------------+------------------------------------+-------------------------+------------------+------------------+-----------+
| 1 | USD | -100.0000 | USD | -100.0000 | USD | 100.0000 | 1005690 | T00 | T00 |
+-----------------+-------------------+-----------+-----------------------------+------------------+------------------------------------+-------------------------+------------------+------------------+-----------+
| 2 | USD | 100.0000 | USD | 100.0000 | USD | 100.0000 | 34180050 | T00 | T00 |
+-----------------+-------------------+-----------+-----------------------------+------------------+------------------------------------+-------------------------+------------------+------------------+-----------+
我理解您的尝试如下:号码必须以2开头,或者以3开头,或者以4开头....除了0,1,5和9之外的任何数字。这更容易放入NOT IN()
-clause
通过此操作,您可以将查询作为派生表获取,您可以使用* normal WHERE
- 子句来过滤:
WITH XMLNAMESPACES(DEFAULT 'http://schema.mycompany.com/Info/2')
,myCTE AS
(
SELECT j.value('@sequence','int') AS JELine_Sequence
,j.value('(Amount/@currencyID)[1]','nvarchar(max)') AS Amount_CurrencyID
,j.value('(Amount)[1]','decimal(14,4)') AS Amount
,j.value('(FunctionalAmount/@currencyID)[1]','nvarchar(max)') AS FunctionalAmount_CurrencyID
,j.value('(FunctionalAmount)[1]','decimal(14,4)') AS FunctionalAmount
,j.value('(ReportingCurrencyAmount/@currencyID)[1]','nvarchar(max)') AS ReportingCurrencyAmount_CurrencyID
,j.value('(ReportingCurrencyAmount)[1]','decimal(14,4)') AS ReportingCurrencyAmount
,j.value('(GLAccount/GLNominalAccount)[1]','bigint') AS GLNominalAccount
,j.value('(GLAccount/AccountingChartReference/ID/@accountingEntity)[1]','nvarchar(max)') AS accountingEntity
,j.value('(GLAccount/AccountingChartReference/ID)[1]','nvarchar(max)') AS AccountID
FROM @xml.nodes('JournalEntry/JELine') AS A(j)
)
SELECT * FROM MyCTE
WHERE LEFT(GLNominalAccount,1) NOT IN('0','1','5','9')
一般来说,最好尽早设置过滤器。这是.nodes()
- 函数,以便不返回不适合过滤器的节点。但在这种情况下,我认为最好返回所有节点并在之后过滤它们(如此处所做)。如果XML包含很多<JELine>
- 节点,那么更改它可能会更好......
答案 1 :(得分:0)
您只需将WHERE条件更改为:
<br>
这是一个完全有效的解决方案(请注意我的评论)
WHERE ParamValues.SSD.value('GLNominalAccount[1]', 'varchar(8)') LIKE '[2-46-8]%'