如何确保SQL能够读取所有XML标记数据

时间:2014-10-17 13:44:15

标签: c# asp.net sql-server xml

我在SQL表列中有以下XML数据:

<root>
    <Physicians>
        <name></name>
        <picture></picture>
        <gender></gender>
        <langAccept>English</langAccept>
        <langAccept>Spanish</langAccept> (can appear more times)
        <insAccept>Aetna</insAccept>
        <insAccept>BCBS</insAccept> (can appear more times)
        <specialty></specialty>
        <specialty2></specialty2>
        <specialty3></specialty3>
    </Physicians>
</root>

langAcceptinsAccept可以多次出现,无法知道多少次。

我有以下SQL查询,目前没有考虑到&#39; langAccept&#39;和&#39; insAccept&#39;标记:

DECLARE @strProvider varchar(200)
SET @strProvider = '' --The Provider DropDownList

DECLARE @strSpecialty varchar(200)
SET @strSpecialty = '' --The Specialty DropDownList

DECLARE @strLocation varchar(200)
SET @strLocation = '' --The Location DropDownList

DECLARE @strGender varchar(200)
SET @strGender = '' --The Gender DropDownList

DECLARE @strInsurance varchar(200)
SET @strInsurance = '' --The Insurance DropDownList

DECLARE @strLanguage varchar(200)
SET @strLanguage = '' --The Language DropDownList


SELECT
    [content_title] AS [Physician Name]
    , [content_status] AS [Status]
    , CAST([content_html] AS XML).value('(root/Physicians/picture/img/@src)[1]','varchar(255)') AS [Image]
    , dbo.usp_ClearHTMLTags(CONVERT(nvarchar(600), CAST([content_html] AS XML).query('root/Physicians/gender'))) AS [Gender]
    , CAST([content_html] AS XML).query('/root/Physicians/OfficeLocations/office1/a') AS [Office1]
    , CAST([content_html] AS XML).query('/root/Physicians/OfficeLocations/office2/a') AS [Office2]
    , CAST([content_html] AS XML).query('/root/Physicians/OfficeLocations/office3/a') AS [Office3]
    , CAST([content_html] AS XML).query('/root/Physicians/OfficeLocations/office4/a') AS [Office4]
    , CAST ([content_html] AS XML).query('/root/Physicians/specialty/a') AS [Specialty1]
    , CAST ([content_html] AS XML).query('/root/Physicians/specialty2/a') AS [Specialty2]
FROM
    [MYDB].[dbo].[content]
WHERE
    [folder_id] = '188'
    AND
    (content_html LIKE '%<gender>%'+ @strGender+'%</gender>%')
    AND
    (content_html LIKE '%'+@strSpecialty+'%')
    AND
    (content_html LIKE '%'+@strLocation+'%')
    AND
    (content_status = 'A')
ORDER BY
    [content_title]

我将使用C#作为代码隐藏,将这些数据写入我的ASP.net页面中的转发器。

如何修改我的SQL查询,使其获取每个langAcceptinsAccept标记的值(显示的次数)。

3 个答案:

答案 0 :(得分:5)

可以处理可能重复的任意数量的节点 - 但请注意,这将始终为单个条目<Physician>创建大量行。

试试这个:

DECLARE @Content TABLE (ID INT NOT NULL, XmlDAta XML)
INSERT INTO @content VALUES(1, '<root>
    <Physicians>
        <name>Dr. Excellent</name>
        <picture></picture>
        <gender>Male</gender>
        <langAccept>English</langAccept>
        <langAccept>Spanish</langAccept> 
        <insAccept>Aetna</insAccept>
        <insAccept>BCBS</insAccept> 
        <specialty></specialty>
        <specialty2></specialty2>
        <specialty3></specialty3>
    </Physicians>
</root>')

SELECT
    ID,
    PhysicianName = XC.value('(name)[1]', 'varchar(50)'),
    Gender = XC.value('(gender)[1]', 'varchar(50)'),
    LangSpoken = XLang.value('.', 'varchar(20)'),
    InsAccepted = XIns.value('.', 'varchar(50)')
FROM
    @Content
CROSS APPLY
    XmlData.nodes('/root/Physicians') AS XT(XC)
CROSS APPLY
    XC.nodes('langAccept') AS XT2(XLang)
CROSS APPLY
    XC.nodes('insAccept') AS XT3(XIns)

.nodes()节点内的langAcceptinsAccept上使用<Physician>,您可以获得所有定义的值 - 但最终会得到几个关系行单个<Physican>节点:

enter image description here

更新:从您自己的现有表中获取数据,请使用:

SELECT
    ID,
    PhysicianName = XC.value('(name)[1]', 'varchar(50)'),
    Gender = XC.value('(gender)[1]', 'varchar(50)'),
    LangSpoken = XLang.value('.', 'varchar(20)'),
    InsAccepted = XIns.value('.', 'varchar(50)')
FROM
    [MyDB].[dbo].Content
CROSS APPLY
    CAST(content_html AS XML).nodes('/root/Physicians') AS XT(XC)
CROSS APPLY
    XC.nodes('langAccept') AS XT2(XLang)
CROSS APPLY
    XC.nodes('insAccept') AS XT3(XIns)

答案 1 :(得分:1)

你可以这样试试。 这不是您问题的确切答案,但这可以帮助您解决问题。

        DECLARE @Data XMl = '<root><Physicians><name>sajsj</name><picture/><gender/><langAccept>English</langAccept><langAccept>Spanish</langAccept> (can appear more times)<insAccept>Aetna</insAccept><insAccept>BCBS</insAccept> (can appear more times)<specialty/><specialty2/><specialty3/></Physicians></root>';

        ;WITH CTE AS (

        SELECT Dt.value('(name/text())[1]','VARCHAR(100)') AS Name,
               Dt.query('(langAccept)') AS LangAccept,
               Dt.query('(insAccept)') AS InsAccept
        FROM 
        @Data.nodes('/root/Physicians') AS MyData(Dt)
        ),
        CteGetAllLangAccept AS 
        (

         SELECT 
         Ct.Name,
         Data.Lang.value('(.)[1]', 'VARCHAR(50)') AS [LangAcceptValue],
         NULL AS [InsAcceptDataValue]
         FROM  CTE Ct
         CROSS APPLY Ct.LangAccept.nodes('/langAccept') AS Data(Lang)

         ),
         CteGetInsAcceptData AS (
          SELECT 
         Ct.Name,
         NULL AS [LangAcceptValue],
         InsAcceptData.Ins.value('(.)[1]', 'VARCHAR(50)') AS [InsAcceptDataValue]
         FROM  CTE Ct
         CROSS APPLY Ct.InsAccept.nodes('/insAccept') AS InsAcceptData(Ins)
         )

         SELECT * FROM CteGetAllLangAccept![enter image description here][1]
         UNION 
         SELECT * FROM CteGetInsAcceptData;

Check the output here.0

答案 2 :(得分:1)

我认为如果你想在客户端展示它,就可以更容易地做几个查询,一个用于医生表,一个用于langAccept,一个用于insAccept

declare @temp table (data xml)

insert into @temp (data)
select '<root>
    <Physicians>
        <name>House M.D.</name>
        <picture></picture>
        <gender>Male</gender>
        <langAccept>English</langAccept>
        <langAccept>Spanish</langAccept> 
        <insAccept>Aetna</insAccept>
        <insAccept>BCBS</insAccept> 
        <specialty></specialty>
        <specialty2></specialty2>
        <specialty3></specialty3>
    </Physicians>
    <Physicians>
        <name>Paracelsus</name>
        <picture></picture>
        <gender>Male</gender>
        <langAccept>German</langAccept>
        <langAccept>Latin</langAccept> 
        <specialty></specialty>
        <specialty2></specialty2>
        <specialty3></specialty3>
    </Physicians>    
</root>'

select
    t.c.value('name[1]', 'nvarchar(max)') as name,
    t.c.value('gender[1]', 'nvarchar(max)') as gender
from @temp as a
    cross apply a.data.nodes('root/Physicians') as t(c)

select
    t.c.value('name[1]', 'nvarchar(max)') as name,
    l.c.value('.', 'nvarchar(max)') as langAccept
from @temp as a
    cross apply a.data.nodes('root/Physicians') as t(c)
    cross apply t.c.nodes('langAccept') as l(c)

select
    t.c.value('name[1]', 'nvarchar(max)') as name,
    l.c.value('.', 'nvarchar(max)') as insAccept
from @temp as a
    cross apply a.data.nodes('root/Physicians') as t(c)
    cross apply t.c.nodes('insAccept') as l(c)

enter image description here