从xml检索数据并获取格式

时间:2018-09-19 14:39:11

标签: sql-server xml sql-server-2008

嗨,我将数据存储在表(cmsContentXml)中,列名称为xml

<Ingredients id="1515" parentID="1062" level="3" creatorID="1" sortOrder="0" createDate="2014-07-23T07:54:58" updateDate="2014-09-06T17:14:45" nodeName="Ingredients" urlName="ingredients" path="-1,1055,1062,1515" isDoc="" nodeType="1514" creatorName="Admin" writerName="ndopuch" writerID="2" template="0" nodeTypeAlias="Ingredients">
  <quickList>
     <![CDATA[1526,1530,1531,1536,1539,1549,1560,1564,1565,1567,1569,1572,1586,1587,1592,1594,1600,1601,1602,1651,1658,1660,1682,1696,1693,1715,1716,1717,1771,1799,1615,1669,1676,1685,1697,1730,1746,1757,1768,1779,1778,1785,1789,1794,1803,1805,1813,1826,1830,1843,1852,1858,1866,1880,1917,1913,1920,1927,1931,1936,1956,1959,1872]]>
  </quickList>
</Ingredients>

我想从路径部分获取如下“ -1,1055,1062,1515”的数据,而1526,1530,1531来自xml节点的quickList

-1,1055,1062,1515,1526
-1,1055,1062,1515,1530
-1,1055,1062,1515,1531
-1,1055,1062,1515,1536
.
.
.
-1,1055,1062,1515,1872

我尝试以

的方式检索数据
SELECT
[xml].value('(/Ingredients/quickList)', 'nvarchar(max)') as data
FROM [cmsContentXml]  where [nodeId]=1515

但给出错误

Cannot find either column "xml" or the user-defined function or aggregate "xml.value", or the name is ambiguous.

样本数据格式

CREATE TABLE #cmsContentXml(
    nodeid [int],
    [xml] [nvarchar](max) NOT NULL    
)

INSERT INTO #cmsContentXml VALUES (1515,'<Ingredients id="1515" parentID="1062" level="3" creatorID="1" sortOrder="0" createDate="2014-07-23T07:54:58" updateDate="2014-09-06T17:14:45" nodeName="Ingredients" urlName="ingredients" path="-1,1055,1062,1515" isDoc="" nodeType="1514" creatorName="Admin" writerName="ndopuch" writerID="2" template="0" nodeTypeAlias="Ingredients">
    <quickList><![CDATA[1526,1530,1531,1536,1539,1549,1560,1564,1565,1567,1569,1572,1586,1587,1592,1594,1600,1601,1602,1651,1658,1660,1682,1696,1693,1715,1716,1717,1771,1799,1615,1669,1676,1685,1697,1730,1746,1757,1768,1779,1778,1785,1789,1794,1803,1805,1813,1826,1830,1843,1852,1858,1866,1880,1917,1913,1920,1927,1931,1936,1956,1959,1872]]></quickList>
</Ingredients>
');

请帮助我以

的方式检索数据
 Data_Column
-1,1055,1062,1515,1526
-1,1055,1062,1515,1530
-1,1055,1062,1515,1531
-1,1055,1062,1515,1536
.
.
.
-1,1055,1062,1515,1872

2 个答案:

答案 0 :(得分:0)

这应该有效:

DECLARE @xml xml ='<Ingredients id="1515" parentID="1062" level="3" creatorID="1" sortOrder="0" createDate="2014-07-23T07:54:58" updateDate="2014-09-06T17:14:45" nodeName="Ingredients" urlName="ingredients" path="-1,1055,1062,1515" isDoc="" nodeType="1514" creatorName="Admin" writerName="ndopuch" writerID="2" template="0" nodeTypeAlias="Ingredients">
  <quickList>
     <![CDATA[1526,1530,1531,1536,1539,1549,1560,1564,1565,1567,1569,1572,1586,1587,1592,1594,1600,1601,1602,1651,1658,1660,1682,1696,1693,1715,1716,1717,1771,1799,1615,1669,1676,1685,1697,1730,1746,1757,1768,1779,1778,1785,1789,1794,1803,1805,1813,1826,1830,1843,1852,1858,1866,1880,1917,1913,1920,1927,1931,1936,1956,1959,1872]]>
  </quickList>
</Ingredients>'

SELECT Path+','+Num FROM (
    SELECT Path.value('.', 'nvarchar(MAX)')
    FROM @xml.nodes('Ingredients/@path') X(Path)
) T1(Path)
CROSS JOIN (
    SELECT REPLACE(REPLACE(A.value('.','nvarchar(MAX)'),' ',''),char(10),'') FROM
    (
        SELECT CAST('<a>'+REPLACE(quickList.value('.','nvarchar(MAX)'),',','</a><a>')+'</a>' as xml) X
        FROM @xml.nodes('Ingredients/quickList') X(quickList)
    ) qlXml
    CROSS APPLY X.nodes('a') T(A)
) T2(Num)

答案 1 :(得分:0)

您面临的第一个问题是您像处理xml这样处理nvarchar的事实。要执行任何操作,必须将其转换为xml。

您遇到的另一个问题是查询:您必须提到使用text()

获取节点内部内容的sql server。

以下问题是您必须要求使用[1]来获取xml的第一个元素的事实,否则sql server将无法知道您要如何处理可能得到的列表。

然后,您将需要分割从xml获得的字符串。从sql server 2016开始,您具有STRING_SPLIT函数。最后,用cross apply在您的行上分配所有拆分的值。

with parsedAsXml as (
    select 
        c.nodeId as NodeId, 
        cast(c.[xml] as xml) as [xml]
    FROM 
        #cmsContentXml as c
),
sub as (
    SELECT 
        c.nodeId as NodeId, 
        c.[xml].value('(/Ingredients/quickList/text())[1]', 'nvarchar(max)') as QuickList,
        c.[xml].value('(/Ingredients/@path)[1]', 'nvarchar(max)') as path
    FROM 
        parsedAsXml as c
)
SELECT 
    s.[path] + ',' + ql.[Value]
FROM 
    sub as s
    cross apply STRING_SPLIT(s.QuickList, ',') as ql
where 
    s.NodeId=1515;

如果您使用的是sql server 2008,则必须创建自己的分割函数(在这里称为splitstring,是从T-SQL split string卑鄙复制的)。

CREATE FUNCTION dbo.splitstring (@stringToSplit VARCHAR(MAX), @separator VARCHAR(50) )
RETURNS
 @returnList TABLE ([Value] [nvarchar] (500))
AS
BEGIN

 DECLARE @name NVARCHAR(255)
 DECLARE @pos INT

 WHILE CHARINDEX(@separator, @stringToSplit) > 0
 BEGIN
  SELECT @pos  = CHARINDEX(@separator, @stringToSplit)  
  SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)

  INSERT INTO @returnList 
  SELECT @name

  SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
 END

 INSERT INTO @returnList
 SELECT @stringToSplit

 RETURN
END
GO