我的示例 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
你把这件事想得太复杂了。除非您需要
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');