添加列名作为XML节点并与其他表连接

问题描述 投票:0回答:1
  1. 我正在尝试查询表列名称作为 XML 节点的值,并在同一节点中添加另一个表中的值。我在其他帖子中找到了一个代码,可以从列名创建节点,但我无法从其他表添加节点。
  2. 我的第二个问题是我想要具有列原始类型的节点。但我还没有找到任何可以帮助我的东西。

我的示例 XML 应如下所示:

<Product>
<ProductName>Product1</ProductName>
<Attributes>
    <Attribute>
        <Name>Attr1</Name>
        <Value>True</Value>
                <Type>BOOL</Type>
    </Attribute>
    <Attribute>
        <Name>Attr2</Name>
            <Value>1.0000000000</Value>
                <Type>DECIMAL</Type>
        </Attribute>
        <Attribute>
        <Name>Weight</Name>
            <Value>155</Value>
                <Type>INT</Type>
        </Attribute>
</Attributes>

</Product>
CREATE TABLE PRODUCT(ProductID int, ProductName nvarchar(40))
INSERT INTO PRODUCT (1, 'Product1')
CREATE TABLE PRODUCT_WEIGHT(ProductID int, CurrentWeight int)
INSERT INTO PRODUCT_WEIGHT(1,155)
CREATE TABLE ATTRIBUTE_(ProductID int, Attr1 BIT, Attr2 decimal(28,10), Attr3 nvarchar(40), Attr4 int)
INSERT INTO ATTRIBUTE_ (1, 1, 1.0, NULL, NULL)

SELECT
ProductName
(
                SELECT(SELECT 
                      C.Name AS [Attribute/Name],
                  C.Value AS [Attribute/Value]
                 FROM  ATTRIBUTE_ A
                 JOIN PRODUCT_WEIGHT pw 
                    ON a.ProductID= pw.ProductID
                 CROSS APPLY (SELECT XMLData = CAST((SELECT a.* FOR XML RAW) AS XML)) B
                 CROSS APPLY (
                                SELECT Name = attr.value('local-name(.)','varchar(100)'),
                                       Value = attr.value('.','varchar(max)')
                                 FROM  B.XMLData.nodes('/row') as A(r)
                                 CROSS APPLY A.r.nodes('./@*') AS B(attr)
                                 WHERE attr.value('local-name(.)','varchar(100)') IN ('Attr1','Attr2', 'Attr3','Weight') 
                             ) C
                WHERE a.ProductID = p.ProductID
                FOR XML PATH(''),TYPE)
                FOR XML PATH ('Attributes'),TYPE
            )

FROM PRODUCT p
FOR XML PATH(''),ROOT('Product')

当我尝试时:

(SELECT a.*,pw.* FOR XML RAW) AS XML)

它给了我一个错误:交易已中止。 我也尝试过:

SELECT
ProductName
(
                SELECT(SELECT 
                      C.Name AS [Attribute/Name],
                  C.Value AS [Attribute/Value]
                 FROM  ATTRIBUTE_ A
                 JOIN PRODUCT_WEIGHT pw 
                    ON a.ProductID= pw.ProductID
                 CROSS APPLY (SELECT XMLData = CAST((SELECT a.* FOR XML RAW) AS XML)) B
                 CROSS APPLY (
                                SELECT Name = attr.value('local-name(.)','varchar(100)'),
                                       Value = attr.value('.','varchar(max)')
                                 FROM  B.XMLData.nodes('/row') as A(r)
                                 CROSS APPLY A.r.nodes('./@*') AS B(attr)
                                 WHERE attr.value('local-name(.)','varchar(100)') IN ('Attr1','Attr2','CurrentWeight') 
                             ) C
                WHERE a.ProductID = p.ProductID
                FOR XML PATH(''),TYPE)
                FOR XML PATH ('Attributes'),TYPE
            ),
(SELECT 'CurrentWeight' AS [Attribute/Name], CurrentWeight AS [Attribute/Value]
FROM PRODUCT_WEIGHT pw2
WHERE pw2.ProductID = p.ProductID
FOR XML PATH('Attibutes'))

FROM PRODUCT p
FOR XML PATH(''),ROOT('Product')

但它只是复制了属性节点。 SQL 版本 2019

  1. 如何实现从不同表添加节点?
  2. 如何添加另一个具有列类型的节点?
sql sql-server t-sql xpath xquery-sql
1个回答
0
投票

你把这件事想得太复杂了。除非您需要

ATTRIBUTE_
列名称是动态的,否则您只需使用
CROSS APPLY (VALUES
来取消透视它们,并将它们全部转换为
sql_variant
,使用
SQL_VARIANT_PROPERTY
来获取基本类型。

你还可以大大简化子查询。

SELECT
  ProductName,
  (
    SELECT
        v.Name,
        v.Value,
        SQL_VARIANT_PROPERTY(v.Value, 'BaseType') AS Type
    FROM ATTRIBUTE_ A
    JOIN PRODUCT_WEIGHT pw ON a.ProductID = pw.ProductID
    CROSS APPLY (VALUES
        ('Attr1',         CAST(A.Attr1          AS sql_variant)),
        ('Attr2',         CAST(A.Attr1          AS sql_variant)),
        ('CurrentWeight', CAST(pw.CurrentWeight AS sql_variant))
    ) v(Name, Value)
    WHERE a.ProductID = p.ProductID
    FOR XML PATH('Attribute'), TYPE, ROOT('Attributes')
  )
FROM PRODUCT p
FOR XML PATH(''), ROOT('Product');

db<>小提琴

© www.soinside.com 2019 - 2024. All rights reserved.