【问题标题】:Extract data from XML data type field in SQL Server从 SQL Server 中的 XML 数据类型字段中提取数据
【发布时间】:2020-04-16 16:24:34
【问题描述】:

我在 ReportServer 数据库上执行以下查询。

SELECT ItemID, CAST(CAST(Content AS VARBINARY(MAX)) AS XML) Content
FROM dbo.Catalog
WHERE Type = 8

我想提取Content 列的字段列表。 content 列是 XML 数据类型并包含如下 XML:

<SharedDataSet xmlns="http://schemas.microsoft.com/sqlserver/reporting/2010/01/shareddatasetdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">
  <DataSet Name="DataSet1">
    <Query>
      <DataSourceReference>DDSDB</DataSourceReference>
      <CommandText>SELECT z.AccessoryPercent
    ,CASE 
        WHEN z.AccessoryPercent&gt;0.20 Then 1 
        WHEN z.AccessoryPercent &gt;=0.10 THEN 0 
        ELSE -1
    end AS AccessoryState
FROM (
    SELECT (a.FixedPrice - a.NetSalesPrice)/a.FixedPrice AS AccessoryPercent
    FROM acc.Fact_Crm_Accessory a
    )z</CommandText>
    </Query>
    <Fields>
      <Field Name="AccessoryPercent">
        <DataField>AccessoryPercent</DataField>
        <rd:TypeName>System.Decimal</rd:TypeName>
      </Field>
      <Field Name="AccessoryState">
        <DataField>AccessoryState</DataField>
        <rd:TypeName>System.Int32</rd:TypeName>
      </Field>
    </Fields>
  </DataSet>
</SharedDataSet>

我的预期结果是:

   DataSetName      Field
   -------------------------------------
   DataSet1         AccessoryPercent
   DataSet1         AccesspryState

提前致谢

编辑:我编写了以下查询以便于查询。

CREATE TABLE #t (data XML)

INSERT INTO #t 
VALUES('<SharedDataSet xmlns="http://schemas.microsoft.com/sqlserver/reporting/2010/01/shareddatasetdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">
<DataSet Name="DataSet1">
    <Query>
      <DataSourceReference>DDSDB</DataSourceReference>
      <CommandText>SELECT z.AccessoryPercent
    ,CASE 
        WHEN z.AccessoryPercent&gt;0.20 Then 1 
        WHEN z.AccessoryPercent &gt;=0.10 THEN 0 
        ELSE -1
    end AS AccessoryState
FROM (
    SELECT (a.FixedPrice - a.NetSalesPrice)/a.FixedPrice AS AccessoryPercent
    FROM acc.Fact_Crm_Accessory a
    )z</CommandText>
    </Query>
    <Fields>
      <Field Name="AccessoryPercent">
        <DataField>AccessoryPercent</DataField>
        <TypeName>System.Decimal</TypeName>
      </Field>
      <Field Name="AccessoryState">
        <DataField>AccessoryState</DataField>
        <TypeName>System.Int32</TypeName>
      </Field>
    </Fields>
  </DataSet>
</SharedDataSet>')

SELECT  *
FROM #t AS t

【问题讨论】:

    标签: sql sql-server xml


    【解决方案1】:

    (1) 我们需要考虑默认命名空间。

    (2) 第二个CROSS APPLY 处理数据集与其字段之间的一对多关系。

    SQL

    -- DDL and sample data population, start
    DECLARE @tbl TABLE (xmldata XML);
    
    INSERT INTO @tbl 
    VALUES('<SharedDataSet xmlns="http://schemas.microsoft.com/sqlserver/reporting/2010/01/shareddatasetdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">
    <DataSet Name="DataSet1">
        <Query>
          <DataSourceReference>DDSDB</DataSourceReference>
          <CommandText>SELECT z.AccessoryPercent
        ,CASE 
            WHEN z.AccessoryPercent&gt;0.20 Then 1 
            WHEN z.AccessoryPercent &gt;=0.10 THEN 0 
            ELSE -1
        end AS AccessoryState
    FROM (
        SELECT (a.FixedPrice - a.NetSalesPrice)/a.FixedPrice AS AccessoryPercent
        FROM acc.Fact_Crm_Accessory a
        )z</CommandText>
        </Query>
        <Fields>
          <Field Name="AccessoryPercent">
            <DataField>AccessoryPercent</DataField>
            <TypeName>System.Decimal</TypeName>
          </Field>
          <Field Name="AccessoryState">
            <DataField>AccessoryState</DataField>
            <TypeName>System.Int32</TypeName>
          </Field>
        </Fields>
      </DataSet>
    </SharedDataSet>');
    -- DDL and sample data population, end
    
    ;WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/sqlserver/reporting/2010/01/shareddatasetdefinition')
    SELECT c.value('@Name','VARCHAR(30)') AS DataSetName      
        , f.value('@Name','VARCHAR(30)') AS Field      
    FROM @tbl AS tbl
        CROSS APPLY tbl.xmldata.nodes('/SharedDataSet/DataSet') AS t(c)
        CROSS APPLY t.c.nodes('Fields/Field') AS f(f);
    

    输出

    +-------------+------------------+
    | DataSetName |      Field       |
    +-------------+------------------+
    | DataSet1    | AccessoryPercent |
    | DataSet1    | AccessoryState   |
    +-------------+------------------+
    

    【讨论】:

      猜你喜欢
      • 2021-07-10
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      • 2010-10-27
      • 1970-01-01
      • 1970-01-01
      • 2020-06-17
      相关资源
      最近更新 更多