将存储在另一个 table 的 varchar(max) 列中的 XML 文件中的数据插入 SQL table

Insert data into SQL table from XML file stored in varchar(max) column of another table

我的 table Table1.State varchar(max) 列包含一个 XML 文件,看起来像这样:

<?xml version="1.0"?><?xml-stylesheet type='text/xsl' href='MyObject.xsl'?>
<MyProperties>
<SortingState
  Before="[{&quot;Sorting&quot;:1
           ,&quot;Type&quot;:4
           ,&quot;Enabled&quot;:false}]" 
  After="[{&quot;Sorting&quot;:2
           ,&quot;Type&quot;:0
           ,&quot;Enabled&quot;:true}]" />
<Appearance
  Before="[{&quot;Transparent&quot;:1
           ,&quot;Color&quot;:Red
           ,&quot;Border&quot;:10}]" 
   After="[{&quot;Transparent&quot;:0
           ,&quot;Color&quot;:Blue
           ,&quot;Border&quot;:8}]]" />
</MyProperties>

我想知道如何将此 Table1.State 列读入临时 table 或 table 变量,以便将文件转换为 table,如下所示:

SortingState Before    Sorting        1
SortingState Before    Type           4 
SortingState Before    Enabled        false 
SortingState After     Sorting        2
SortingState After     Type           0 
SortingState After     Enabled        true
Appearance   Before    Transparent    1
Appearance   Before    Color          Red 
Appearance   Before    Border         10 
Appearance   After     Transparent    0
Appearance   After     Color          Blue 
Appearance   After     Border         8

好吧,这不是最漂亮的解决方案,但它会产生您请求的输出。我使用您提供的 XML 创建了一个 varchar(max) 变量 @XmlText (为了包含在字符串文字中,将几个单引号更新为双单引号除外)。将其转换为 xml 数据类型的变量,然后解析:

DECLARE @XmlText varchar(max) = 
'<?xml version="1.0"?><?xml-stylesheet type=''text/xsl'' href=''MyObject.xsl''?>
<MyProperties>
<SortingState
  Before="[{&quot;Sorting&quot;:1
           ,&quot;Type&quot;:4
           ,&quot;Enabled&quot;:false}]" 
  After="[{&quot;Sorting&quot;:2
           ,&quot;Type&quot;:0
           ,&quot;Enabled&quot;:true}]" />
<Appearance
  Before="[{&quot;Transparent&quot;:1
           ,&quot;Color&quot;:Red
           ,&quot;Border&quot;:10}]" 
   After="[{&quot;Transparent&quot;:0
           ,&quot;Color&quot;:Blue
           ,&quot;Border&quot;:8}]]" />
</MyProperties>'; 

DECLARE @Xml xml = CAST(@XmlText AS xml); 
SELECT 
    my_properties_nodes.xml_frag.value('fn:local-name(.)','varchar(20)') AS Column1
    ,first_level_attributes.xml_frag.value('local-name(.)','varchar(10)') AS Column2
    ,SUBSTRING(RTRIM(LTRIM(ss.value)), CHARINDEX('"', RTRIM(LTRIM(ss.value)), 1) + 1, CHARINDEX('"', RTRIM(LTRIM(ss.value)), CHARINDEX('"', RTRIM(LTRIM(ss.value)), 1) + 1) - CHARINDEX('"', RTRIM(LTRIM(ss.value)), 1) - 1) AS Column3
    ,CASE 
        WHEN CHARINDEX('}', RTRIM(LTRIM(ss.value)), 1) > 1
            THEN SUBSTRING(RTRIM(LTRIM(ss.value)), CHARINDEX(':', RTRIM(LTRIM(ss.value)), 1) + 1, CHARINDEX('}', RTRIM(LTRIM(ss.value)), 1) - CHARINDEX(':', RTRIM(LTRIM(ss.value)), 1) - 1)
        ELSE RIGHT(RTRIM(LTRIM(ss.value)), LEN(RTRIM(LTRIM(ss.value))) - CHARINDEX(':', RTRIM(LTRIM(ss.value)), 1)) 
    END AS Column4
FROM 
    @Xml.nodes('/MyProperties/*') AS my_properties_nodes(xml_frag)
    CROSS APPLY my_properties_nodes.xml_frag.nodes('@*') AS first_level_attributes(xml_frag) 
    CROSS APPLY string_split(first_level_attributes.xml_frag.value('.','varchar(max)'), ',') AS ss;

查询从 MyProperties 元素正下方的每个子元素的一行开始,为第一个子元素的每个属性增加行,然后通过拆分的值再次增加行属性(使用 string_split 逗号。然后我只是手动解析值。Column3 在第一个和第二个 " 之间解析。Column4 在第一个 : 和字符串的结尾,或者第一个 : 和第一个 } 之间,具体取决于字符串是否包含 } 字符。

希望这对您有所帮助。

此外,您可以从包含此文本的 table 中使用它,就像使用 OUTER APPLY 将您的 varchar(max) 列转换为 xml 一样。然后将 CROSS APPLY 用于第一个 @Xml.nodes('/MyProperties/*') AS my_properties_nodes(xml_frag) 并将 @Xml 替换为对转换后的 xml 值的引用:

.......
FROM 
    MyTable AS tbl_a
    OUTER APPLY (SELECT CAST(tbl_a.VarcharMaxColumn AS xml) AS ConvertedXml) AS cast_xml
    CROSS APPLY cast_xml.ConvertedXml.nodes('/MyProperties/*') AS my_properties_nodes(xml_frag)
.......