创建 XML 文件时在 SQL 中联合

Posted

技术标签:

【中文标题】创建 XML 文件时在 SQL 中联合【英文标题】:Union in SQL while creating XML file 【发布时间】:2016-05-25 07:18:25 【问题描述】:

我在创建 XML 文件的 SQL 查询时遇到了一些问题。我想做UNION这个查询,但它不起作用。

(SELECT 1 AS "ns0:kindOfItem",
code AS "ns0:wholeCode",
REPLACE(weight, ',', '.') AS "ns0:weight",
1 AS "ns0:ammountOfNumbers",
(SELECT price AS "ns0:value",
'EUR' as "ns0:currency"
FOR XML PATH ('ns0:sendedItems'), TYPE),
(SELECT 
'EUR' as "ns0:currency"
FOR XML PATH ('ns0:present'), TYPE)
FROM [PL].[dbo].[dk_documents] where id in (1,2,3)
FOR XML PATH('test'))

这个查询工作正常,但是当我尝试像这里一样做UNION 时:

(SELECT 1 AS "ns0:kindOfItem",
code AS "ns0:wholeCode",
REPLACE(weight, ',', '.') AS "ns0:weight",
1 AS "ns0:ammountOfNumbers",
(SELECT price AS "ns0:value",
'EUR' as "ns0:currency"
FOR XML PATH ('ns0:sendedItems'), TYPE),
(SELECT 
'EUR' as "ns0:currency"
FOR XML PATH ('ns0:present'), TYPE)
FROM [PL].[dbo].[dk_documents] where id in (1,2,3)

UNION

(SELECT 1 AS "ns0:kindOfItem",
code AS "ns0:wholeCode",
REPLACE(weight, ',', '.') AS "ns0:weight",
1 AS "ns0:ammountOfNumbers",
(SELECT price AS "ns0:value",
'EUR' as "ns0:currency"
FOR XML PATH ('ns0:sendedItems'), TYPE),
(SELECT 
'EUR' as "ns0:currency"
FOR XML PATH ('ns0:present'), TYPE)
FROM [PL2].[dbo].[dk_documents] where id in (1,2,3)
FOR XML PATH('test'))

这个查询给我一个错误:

数据类型 xml 不能用作 UNION、INTERSECT 的操作数 或 EXCEPT 运算符,因为它不可比较。

【问题讨论】:

错误信息很清楚,您的选择至少有一列的数据类型不兼容。 (第 1 列必须一直兼容,第 2、第 3 等也是如此。) 我有点知道 :) 但我不知道如何解决它,当我在没有“FOR XML PATH ('ns0:sendedItems'), TYPE)”和“FOR XML”的情况下执行此查询时PATH ('ns0:present'), TYPE)" 它可以正常工作,但是 xml 架构不正常。 我不确定我是否完全理解您要做什么,但可能先 union 数据,然后从中生成 xml,而不是合并两个 xml。 是的,但我不知道该怎么做。 【参考方案1】:

使用UNION 将删除结果的重复值,因此 SQL Server 必须将第一部分的 XML 与第二部分的 XML 进行比较,并确定它们是否相等且未针对 XML 实现。

您可能不希望重复检查,因此改为UNION ALL,它也适用于 XML 数据。

【讨论】:

谢谢队友 :) 我把它改成 UNION ALL 并且它工作正常【参考方案2】:

您可能对此感兴趣:

请比较以下

“测试”一词出现在两个列表中。 UNION 会隐式执行 DISTINCT,因此“测试”只出现一次。

SELECT * 
FROM (VALUES('this'),('is'),('a'),('test')) AS tbl(Words)
UNION
SELECT * 
FROM (VALUES('and'),('another'),('test')) AS tbl(Words);

UNION ALL一样会让“测试”出现两次

SELECT * 
FROM (VALUES('this'),('is'),('a'),('test')) AS tbl(Words)
UNION ALL
SELECT * 
FROM (VALUES('and'),('another'),('test')) AS tbl(Words);

您可以将UNION SELECT 放入周围的SELECTUNIONUNION ALL 并为整个结果集设置FOR XML PATH

命名空间是重复创建的,没有错,但很烦人(参见:https://***.com/a/35648751/5089204 和链接的 Connect-Article)

WITH XMLNAMESPACES(DEFAULT 'Dummy') 
SELECT *
FROM
(
    SELECT * 
    FROM (VALUES('this'),('is'),('a'),('test')) AS tbl(Words)
    UNION
    SELECT * 
    FROM (VALUES('and'),('another'),('test')) AS tbl(Words)
) AS MetaTable
FOR XML Path(''),ROOT('UNION_TEST');

这将带回两个列表,每个列表都有自己的 XML 标记,还有重复的命名空间(见前文)

WITH XMLNAMESPACES(DEFAULT 'Dummy') 
SELECT
 (
    SELECT * 
    FROM (VALUES('this'),('is'),('a'),('test')) AS tbl(Words)
    FOR XML PATH(''),ROOT('FirstBlock'),TYPE
 )
,(
    SELECT * 
    FROM (VALUES('and'),('another'),('test')) AS tbl(Words)
    FOR XML PATH(''),ROOT('FirstBlock'),TYPE
 )
FOR XML Path(''),ROOT('UNION_TEST');

最后你也可以使用它(ALL 或不使用):

WITH XMLNAMESPACES(DEFAULT 'Dummy') 
SELECT * 
FROM (VALUES('this'),('is'),('a'),('test')) AS tbl(Words)
UNION ALL
SELECT * 
FROM (VALUES('and'),('another'),('test')) AS tbl(Words)
FOR XML PATH(''),ROOT('UNION_TEST');

【讨论】:

以上是关于创建 XML 文件时在 SQL 中联合的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL Server 中联合所有的替代方案

mybatis中联合查询

实体框架中联合数据“视图”上的 OData

Mysql中联合索引的最左匹配原则(百度)

Ariadne 中联合类型的解析器函数

如何在MYSQL中联合多个表[重复]