SQL Server 2012中的XML AUTO和UNION问题

问题描述 投票:1回答:1

我们正在将SQL Server 2008 R2升级到SQL Server 2012(我知道,我们很少有版本,但这是一个暂时的解决方案)来利用2008年没有的一些功能。在此过程中,我们确定了当UNION语句存在时SQL Server 2012如何处理XML Auto的问题/差异。

这是我想要实现的格式:

<Product Color="Black" EnglishProductName="Full-Finger Gloves, L" Customizable="0">
  <ProductSubCategory EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />
</Product>
<Product Color="Black" EnglishProductName="Full-Finger Gloves, M" Customizable="0">
  <ProductSubCategory EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />
</Product>
<Product Color="Black" EnglishProductName="Full-Finger Gloves, S" Customizable="0">
  <ProductSubCategory EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />
</Product>
<Product Color="Black" EnglishProductName="Half-Finger Gloves, L" Customizable="0">
  <ProductSubCategory EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />
</Product>
<Product Color="Black" EnglishProductName="Half-Finger Gloves, M" Customizable="0">
  <ProductSubCategory EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />
</Product>
<Product Color="Black" EnglishProductName="Half-Finger Gloves, S" Customizable="0">
  <ProductSubCategory EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />
</Product>

以下是产生上述代码的代码(使用AdventureWorksDB):

Select Distinct Product.Color, Product.EnglishProductName, 0 as Customizable,
    ProductSubCategory.EnglishProductSubcategoryName,
    ProductSubCategory.FrenchProductSubcategoryName
    From dbo.DimProduct as Product
    Inner Join dbo.DimProductSubcategory As ProductSubCategory On ProductSubCategory.ProductSubcategoryKey = Product.ProductSubcategoryKey
    For Xml Auto

但是当我添加UNION语句时,它会中断我的XML输出:

<Product Color="Black" EnglishProductName="Full-Finger Gloves, L" Customizable="0" EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />
<Product Color="Black" EnglishProductName="Full-Finger Gloves, L" Customizable="1" EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />
<Product Color="Black" EnglishProductName="Full-Finger Gloves, M" Customizable="0" EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />
<Product Color="Black" EnglishProductName="Full-Finger Gloves, M" Customizable="1" EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />
<Product Color="Black" EnglishProductName="Full-Finger Gloves, S" Customizable="0" EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />
<Product Color="Black" EnglishProductName="Full-Finger Gloves, S" Customizable="1" EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, L" Customizable="0" EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, L" Customizable="1" EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, M" Customizable="0" EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, M" Customizable="1" EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, S" Customizable="0" EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, S" Customizable="1" EnglishProductSubcategoryName="Gloves" FrenchProductSubcategoryName="Gants" />

以下是产生上述代码的代码:

Select Distinct Product.Color, Product.EnglishProductName, 0 as Customizable,
ProductSubCategory.EnglishProductSubcategoryName,
ProductSubCategory.FrenchProductSubcategoryName
From dbo.DimProduct as Product
Inner Join dbo.DimProductSubcategory As ProductSubCategory On ProductSubCategory.ProductSubcategoryKey = Product.ProductSubcategoryKey
Union
Select Distinct Product.Color, Product.EnglishProductName, 1 as Customizable,
ProductSubCategory.EnglishProductSubcategoryName,
ProductSubCategory.FrenchProductSubcategoryName
From dbo.DimProduct as Product
Inner Join dbo.DimProductSubcategory As ProductSubCategory On ProductSubCategory.ProductSubcategoryKey = Product.ProductSubcategoryKey
For Xml Auto

我需要ProductSubCategory在XML输出中保留Product节点的子节点,即使使用UNION语句也是如此。 UNION对2008年的XML输出没有影响,但出于某种原因,SQL Server 2012以不同的方式处理相同的语句。任何帮助表示赞赏。希望我足够清楚。谢谢。

xml sql-server-2012
1个回答
0
投票

下次请提供一些耗材格式的样本数据,最好是DDL,INSERT和您的工作代码作为独立的MCVE。这有很大帮助。这次我为你打字:

一些包含数据的模型表:

DECLARE @Product TABLE(ProductKey INT IDENTITY,Color VARCHAR(100),EnglishProductName VARCHAR(100),ProductSubcategoryKey INT);
INSERT INTO @Product VALUES('Black','Full-Finger Gloves, L',1)
                          ,('Black','Full-Finger Gloves, M',1)
                          ,('Black','Full-Finger Gloves, S',1)
                          ,('Black','Half-Finger Gloves, L',1)
                          ,('Black','Half-Finger Gloves, M',1)
                          ,('Black','Half-Finger Gloves, S',1);

DECLARE @ProductSubCategory TABLE(ProductSubcategoryKey INT IDENTITY,EnglishProductSubcategoryName VARCHAR(100));
INSERT INTO @ProductSubCategory VALUES('Gloves');

- 查询使用FOR XML PATH而不是AUTO模式。我稍后会解释

Select Distinct Product.Color AS [@Color]
              , Product.EnglishProductName AS [@EnglishProductName]
              , 0 as [@Customizable]
              , ProductSubCategory.EnglishProductSubcategoryName AS [ProductSubCategory/@EnglishProductSubcategoryName]
    From @Product as Product
    Inner Join @ProductSubCategory As ProductSubCategory On ProductSubCategory.ProductSubcategoryKey = Product.ProductSubcategoryKey

UNION 
Select Distinct Product.Color AS [@Color]
              , Product.EnglishProductName AS [@EnglishProductName]
              , 1 as [@Customizable]
              , ProductSubCategory.EnglishProductSubcategoryName AS [ProductSubCategory/@EnglishProductSubcategoryName]
    From @Product as Product
    Inner Join @ProductSubCategory As ProductSubCategory On ProductSubCategory.ProductSubcategoryKey = Product.ProductSubcategoryKey
For Xml PATH('Product');

一些解释:

您使用AUTO的方法允许引擎决定您将获得什么。总的来说,我不喜欢这样的想法。内部实施的任何改变都会炸毁生产中的系统。更好地使用PATH,它可以让你对你得到的东西有最深的控制。

一些评论:

不需要工会

如果我正确地得到了这个,你使用UNION只是为了将每个产品添加两次。一行在@Customizable处为零,第二行为1.一个简单的CROSS JOINVALUES设置将做同样的,但更快更好阅读:

Select Distinct Product.Color AS [@Color]
              , Product.EnglishProductName AS [@EnglishProductName]
              , A.Customizable as [@Customizable]
              , ProductSubCategory.EnglishProductSubcategoryName AS [ProductSubCategory/@EnglishProductSubcategoryName]
    From @Product as Product
    Inner Join @ProductSubCategory As ProductSubCategory On ProductSubCategory.ProductSubcategoryKey = Product.ProductSubcategoryKey
    CROSS JOIN (VALUES(1),(0)) A(Customizable)
For Xml PATH('Product')

可读性

使用表别名很好,但我建议使用像这里更短的别名

Select Distinct p.Color AS [@Color]
              , p.EnglishProductName AS [@EnglishProductName]
              , A.Customizable as [@Customizable]
              , sc.EnglishProductSubcategoryName AS [ProductSubCategory/@EnglishProductSubcategoryName]
    From @Product as p
    Inner Join @ProductSubCategory As sc On sc.ProductSubcategoryKey = p.ProductSubcategoryKey
    CROSS JOIN (VALUES(1),(0)) A(Customizable)
For Xml PATH('Product');

结构体

迟早你将拥有一个属于多个SubCategory的产品。我建议将其设计为n:m相关系统,其间有映射表

最终的XML

因为您的SubCategory更类似于产品系列您可能会创建类似的东西

<ProductSubCategory EnglishProductSubcategoryName="Gloves">
    <Product Color="Black" EnglishProductName="Full-Finger Gloves, L" Customizable="0" />
    <Product Color="Black" EnglishProductName="Full-Finger Gloves, L" Customizable="1" />
    <Product Color="Black" EnglishProductName="Full-Finger Gloves, M" Customizable="0" />
    <Product Color="Black" EnglishProductName="Full-Finger Gloves, M" Customizable="1" />
    <Product Color="Black" EnglishProductName="Full-Finger Gloves, S" Customizable="0" />
    <Product Color="Black" EnglishProductName="Full-Finger Gloves, S" Customizable="1" />
    <Product Color="Black" EnglishProductName="Half-Finger Gloves, L" Customizable="0" />
    <Product Color="Black" EnglishProductName="Half-Finger Gloves, L" Customizable="1" />
    <Product Color="Black" EnglishProductName="Half-Finger Gloves, M" Customizable="0" />
    <Product Color="Black" EnglishProductName="Half-Finger Gloves, M" Customizable="1" />
    <Product Color="Black" EnglishProductName="Half-Finger Gloves, S" Customizable="0" />
    <Product Color="Black" EnglishProductName="Half-Finger Gloves, S" Customizable="1" />    
<ProductSubCategory>

甚至更简单

<ProductSubCategory EnglishProductSubcategoryName="Gloves">
  <Customizable value=1>
    <Product Color="Black" EnglishProductName="Full-Finger Gloves, L" />
    <Product Color="Black" EnglishProductName="Full-Finger Gloves, M" />
    <Product Color="Black" EnglishProductName="Full-Finger Gloves, S" />
    <Product Color="Black" EnglishProductName="Half-Finger Gloves, L" />
    <Product Color="Black" EnglishProductName="Half-Finger Gloves, M" />
    <Product Color="Black" EnglishProductName="Half-Finger Gloves, S" />    
  </Customizable>
  <Customizable value=0>
    <Product Color="Black" EnglishProductName="Full-Finger Gloves, L" />
    <Product Color="Black" EnglishProductName="Full-Finger Gloves, M" />
    <Product Color="Black" EnglishProductName="Full-Finger Gloves, S" />
    <Product Color="Black" EnglishProductName="Half-Finger Gloves, L" />
    <Product Color="Black" EnglishProductName="Half-Finger Gloves, M" />
    <Product Color="Black" EnglishProductName="Half-Finger Gloves, S" />    
  </Customizable>
<ProductSubCategory>
© www.soinside.com 2019 - 2024. All rights reserved.