【问题标题】:T-SQL parse XML data into single lineT-SQL 将 XML 数据解析为单行
【发布时间】:2020-08-03 15:36:38
【问题描述】:

我已将 XML 作为类型 nvarchar 保存到表中的列中。现在我需要解析来自xml 的数据。我愿意

SELECT
    CONVERT(XML, columnX).value('(chatTranscript/message/msgText/text())[1]', 'nvarchar(max)') 

作为聊天,但我只得到第一个值。如何将所有内容提取到单行中? XML 可以很长,取决于聊天的长度。

我需要得到userNick,然后是msgText,然后循环到最后。像这样的:

userX:Hello<>userY:How are you; 

XML:

<?xml version="1.0"?>
<chatTranscript startAt="2020-07-30T11:00:12Z" sessionId="......">
    <newParty userId="......" timeShift="0" visibility="ALL" eventId="1">
        <userInfo personId="" userNick="userX"/>
    </newParty>
    <message userId="..." timeShift="12" visibility="ALL" eventId="9">
        <msgText msgType="text">Hello</msgText>
    </message>
    <newParty userId="..." timeShift="15" visibility="ALL" eventId="10">
        <userInfo userNick="userY"/>
    </newParty>
    <message userId="..." timeShift="29" visibility="ALL" eventId="12">
        <msgText treatAs="NORMAL">how are you?</msgText>
    </message>
    <partyLeft userId="..." timeShift="36" visibility="ALL" eventId="13" askerId="...">
        <reason code="1">left with request to close if no agents</reason>
    </partyLeft>
    <partyLeft userId="..." timeShift="36" visibility="ALL" eventId="14" askerId="...">
        <reason code="4">removed by other party</reason>
    </partyLeft>
</chatTranscript>

【问题讨论】:

  • “我已将 xml 作为 nvarchar 保存到表中的列中” 如果是 XML,您为什么使用 nvarchar 而不是 xml 数据类型?
  • babbon,在提出问题时,您需要提供一个可重现的最小示例。请参考以下链接:stackoverflow.com/help/minimal-reproducible-example 请提供以下内容: (1) DDL 和样本数据填充,即 CREATE table(s) 加上 INSERT T-SQL 语句。 (2) 你需要做什么,即逻辑和你的代码尝试实现它。 (3) 期望的输出,基于上面#1 中的样本数据。 (4) 你的 SQL Server 版本 (SELECT @@version;)
  • babbon,你为什么使用元素 ?为什么消息的文本不只是包含在 的文本中?如果您重新设计 xml 架构,您的任务可能会更容易。如果您将使用更通用的元素并使用更具体的类型,则查询可能会更容易。例如。 ... 另外我想知道所需的排序顺序。 timeshift 或 eventId 是否与订购所需输出相关?
  • 我无法更改列类型和 xml 架构。我有我现在需要从中提取数据的东西。我的表包含 id (int) 和 columnX (nvarchar),即 xml 内容。现在我需要从 columnX 中进行选择,这样在没有标签和无用信息的情况下很容易阅读。如果我这样做:选择 id, CONVERT(XML, [columnX]).value('(chatTranscript/newParty/userInfo/@userNick)[1]', 'nvarchar(max)') + ': ' + CONVERT(XML, [columnX]).value('(chatTranscript/message/msgText/text())[1]', 'nvarchar(max)') 从 tableX 我得到“userX: Hello”。但我需要在一行中进行整个对话。
  • @babboon 如果有更多消息怎么办?愿望输出是什么?

标签: sql-server xml tsql parsing


【解决方案1】:

您需要代码来干净利落地执行此操作。尝试做你所要求的将是超级混乱的 T-SQL。我建议在代码中解析 xml 以根据该 xml 生成您想要的内容。您还可以使用代码创建 CLR 函数,以便创建 SQL 函数来执行此操作。您可以使用 XQuery 和 T-SQL 做一些令人惊奇的事情,但有时它会变得一团糟。对于所有在数据库中的 xml 操作,CLR 函数是完美的。

【讨论】:

    【解决方案2】:

    这是我的解决方案:

    ALTER FUNCTION [dbo].[fn_parse_chat_xml] (@xml XML) 
    RETURNS NVARCHAR(MAX) 
    BEGIN 
        DECLARE @n INT, @content NVARCHAR(MAX), @userId NVARCHAR(200), @userNick1 NVARCHAR(200), @userNick2 NVARCHAR(200), @userNickX NVARCHAR(200)
        SET @n = 1 
        SET @userId = @xml.value('(chatTranscript/newParty/@userId)[1]', 'nvarchar(max)')
        SET @userNick1 = @xml.value('(chatTranscript/newParty/userInfo/@userNick)[1]', 'nvarchar(max)')
        SET @userNick2 = @xml.value('(chatTranscript/newParty/userInfo/@userNick)[2]', 'nvarchar(max)')
        WHILE DATALENGTH(@xml.value('(chatTranscript/message/msgText/text())[sql:variable("@n")][1]', 'nvarchar(max)'))>0 
            BEGIN        
                IF @userId = @xml.value('(chatTranscript/message/@userId)[sql:variable("@n")][1]', 'nvarchar(max)') 
                    SET @userNickX = @userNick1
                else 
                    SET @userNickX = @userNick2 
                SET @content = concat(@content, ' <> ', @userNickX, ': ', @xml.value('(chatTranscript/message/msgText/text())[sql:variable("@n")][1]', 'nvarchar(max)'))
                SET @n = @n + 1
            END
        RETURN @content
    END
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-04
      • 2021-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多