SQL 服务器 XML - 基本查询
SQL Server FOR XML - Basic query
我得到了一个 XML 文档,我想通过 SQL 脚本生成它,但我没有做过类似的事情,也找不到任何示例使我能够生成我需要的最终 XML (而且我不确定如果有一种方法更适合我的需要,哪种可能的方法可用 - EXPLICIT 或 PATH 或什至可能)。
我希望有从 SQL 生成 XML 经验的人能够为我指出正确的方向(或者告诉我我正在尝试做的事情是不可能的,而我需要做的)它与子查询)。
场景是我从单个 table 返回产品详细信息(我宁愿不必为我需要的每个值执行子查询)。
我希望能够生成的xml看起来像(我无法控制这种格式):
<records>
<record>
<fields>
<field name="id">
<values>
<value>666111</value>
</values>
</field>
<field name="name">
<values>
<value>
<![CDATA[My Product Title]]>
</value>
</values>
</field>
</fields>
</record>
<record>
...
</record>
</records>
我看过的第一个方法是使用 FOR XML PATH
SELECT TOP 2
'id' AS "@name",
p.product_id as [value],
p.title
FROM products p
ORDER BY p.product_id DESC
FOR XML PATH ('field'), ROOT ('fields'), ELEMENTS;
这给了我 XML:
<fields>
<field name="id">
<value>20624</value>
<title>test154</title>
</field>
<field name="id">
<value>20623</value>
<title>test153</title>
</field>
</fields>
这给了我所需的 '',但我无法指定下一个元素所需的布局。
我也调查了 FOR XML EXPLICIT
SELECT TOP 2
1 AS Tag, NULL AS Parent,
p.product_id AS [record!1!product_id!ELEMENT],
NULL AS [values!2!value!ELEMENT]
FROM products p
UNION ALL
SELECT TOP 2
2, 1,
p.product_id,
p.title
FROM products p
ORDER BY [record!1!product_id!ELEMENT] DESC
FOR XML EXPLICIT;
这给了我以下 XML:
<record>
<product_id>20624</product_id>
<values>
<value>test154</value>
</values>
</record>
<record>
<product_id>20623</product_id>
<values>
<value>test153</value>
</values>
</record>
我有点不知所措,无法建立请求或获得正确的东西(而且我认为我试图在一次查找中做太多事情,这就是我的问题)。感谢任何帮助 - 即使它为我提供了一个很好的指南(我发现的唯一一个在示例方面非常糟糕 - 它们没有显示你如何 build/change 它们的微妙之处)
这是您可能要查找的查询
中间的 ,''
是一个技巧,它允许您创建多个具有相同名称的元素,一个在另一个下面...
DECLARE @tbl TABLE(id INT,name VARCHAR(100));
INSERT INTO @tbl VALUES
(666111,'My Product Title 111')
,(666222,'My Product Title 222');
SELECT
(
SELECT 'id' AS [field/@name]
,id AS [field/values/value]
,''
,'name' AS [field/@name]
,name AS [field/values/value]
FOR XML PATH('fields'),TYPE
)
FROM @tbl AS tbl
FOR XML PATH('record'),ROOT('records')
结果
<records>
<record>
<fields>
<field name="id">
<values>
<value>666111</value>
</values>
</field>
<field name="name">
<values>
<value>My Product Title 111</value>
</values>
</field>
</fields>
</record>
<record>
<fields>
<field name="id">
<values>
<value>666222</value>
</values>
</field>
<field name="name">
<values>
<value>My Product Title 222</value>
</values>
</field>
</fields>
</record>
</records>
更新:据我所知,没有干净的方法来添加 CDATA
-sections
出于某些原因,Microsoft 的人员认为 CDATA 部分不是必需的。好吧,他们不是,但有时他们仍然需要...
添加 CDATA
部分的唯一 干净的方法 是使用 FOR XML EXPLICIT
。另一个 解决方法 是放置类似 '|' + name + '#'
的内容(使用两个字符,这两个字符永远不会出现在您的实际数据中。
然后你可以将结果转换为NVARCHAR(MAX)
,在字符串基础上替换这些字符。
这将 return 你的 XML 作为字符串
SELECT
REPLACE(REPLACE(CAST(
(
SELECT
(
SELECT 'id' AS [field/@name]
,id AS [field/values/value]
,''
,'name' AS [field/@name]
,'|' + name + '#' AS [field/values/value]
FOR XML PATH('fields'),TYPE
)
FROM @tbl AS tbl
FOR XML PATH('record'),ROOT('records')
) AS NVARCHAR(MAX)),'|','<![CDATA['),'#',']]>')
在您将其转换回 XML
的那一刻,CDATA 消失了 :-(
类似的东西
declare @t table (id varchar(10))
insert into @t values ('1')
insert into @t values ('2')
select (
select
t.id 'fields/field/@id'
, t.id 'fields/field/name'
from @t t
for xml path(''), type
) 'records/record'
for xml path('')
我最后用的SQL是:
SELECT TOP 2
(
SELECT
(SELECT 'id' AS [field/@id],
product_id [field/values/value]
FOR XML PATH(''), TYPE),
(SELECT 'title' AS [field/@id],
title [field/values/value]
FOR XML PATH(''), TYPE)
FOR XML PATH('fields'), TYPE
)
FROM products
FOR XML PATH('record'), ROOT('records')
因为这让我可以更轻松地操作输出。
感谢@xdd,尤其是@Shnugo 的回答!最终的解决方案是基于@Shnugo 的建议,只是避免了插入额外空白行的技巧。
我得到了一个 XML 文档,我想通过 SQL 脚本生成它,但我没有做过类似的事情,也找不到任何示例使我能够生成我需要的最终 XML (而且我不确定如果有一种方法更适合我的需要,哪种可能的方法可用 - EXPLICIT 或 PATH 或什至可能)。 我希望有从 SQL 生成 XML 经验的人能够为我指出正确的方向(或者告诉我我正在尝试做的事情是不可能的,而我需要做的)它与子查询)。
场景是我从单个 table 返回产品详细信息(我宁愿不必为我需要的每个值执行子查询)。
我希望能够生成的xml看起来像(我无法控制这种格式):
<records>
<record>
<fields>
<field name="id">
<values>
<value>666111</value>
</values>
</field>
<field name="name">
<values>
<value>
<![CDATA[My Product Title]]>
</value>
</values>
</field>
</fields>
</record>
<record>
...
</record>
</records>
我看过的第一个方法是使用 FOR XML PATH
SELECT TOP 2
'id' AS "@name",
p.product_id as [value],
p.title
FROM products p
ORDER BY p.product_id DESC
FOR XML PATH ('field'), ROOT ('fields'), ELEMENTS;
这给了我 XML:
<fields>
<field name="id">
<value>20624</value>
<title>test154</title>
</field>
<field name="id">
<value>20623</value>
<title>test153</title>
</field>
</fields>
这给了我所需的 '',但我无法指定下一个元素所需的布局。
我也调查了 FOR XML EXPLICIT
SELECT TOP 2
1 AS Tag, NULL AS Parent,
p.product_id AS [record!1!product_id!ELEMENT],
NULL AS [values!2!value!ELEMENT]
FROM products p
UNION ALL
SELECT TOP 2
2, 1,
p.product_id,
p.title
FROM products p
ORDER BY [record!1!product_id!ELEMENT] DESC
FOR XML EXPLICIT;
这给了我以下 XML:
<record>
<product_id>20624</product_id>
<values>
<value>test154</value>
</values>
</record>
<record>
<product_id>20623</product_id>
<values>
<value>test153</value>
</values>
</record>
我有点不知所措,无法建立请求或获得正确的东西(而且我认为我试图在一次查找中做太多事情,这就是我的问题)。感谢任何帮助 - 即使它为我提供了一个很好的指南(我发现的唯一一个在示例方面非常糟糕 - 它们没有显示你如何 build/change 它们的微妙之处)
这是您可能要查找的查询
中间的 ,''
是一个技巧,它允许您创建多个具有相同名称的元素,一个在另一个下面...
DECLARE @tbl TABLE(id INT,name VARCHAR(100));
INSERT INTO @tbl VALUES
(666111,'My Product Title 111')
,(666222,'My Product Title 222');
SELECT
(
SELECT 'id' AS [field/@name]
,id AS [field/values/value]
,''
,'name' AS [field/@name]
,name AS [field/values/value]
FOR XML PATH('fields'),TYPE
)
FROM @tbl AS tbl
FOR XML PATH('record'),ROOT('records')
结果
<records>
<record>
<fields>
<field name="id">
<values>
<value>666111</value>
</values>
</field>
<field name="name">
<values>
<value>My Product Title 111</value>
</values>
</field>
</fields>
</record>
<record>
<fields>
<field name="id">
<values>
<value>666222</value>
</values>
</field>
<field name="name">
<values>
<value>My Product Title 222</value>
</values>
</field>
</fields>
</record>
</records>
更新:据我所知,没有干净的方法来添加 CDATA
-sections
出于某些原因,Microsoft 的人员认为 CDATA 部分不是必需的。好吧,他们不是,但有时他们仍然需要...
添加 CDATA
部分的唯一 干净的方法 是使用 FOR XML EXPLICIT
。另一个 解决方法 是放置类似 '|' + name + '#'
的内容(使用两个字符,这两个字符永远不会出现在您的实际数据中。
然后你可以将结果转换为NVARCHAR(MAX)
,在字符串基础上替换这些字符。
这将 return 你的 XML 作为字符串
SELECT
REPLACE(REPLACE(CAST(
(
SELECT
(
SELECT 'id' AS [field/@name]
,id AS [field/values/value]
,''
,'name' AS [field/@name]
,'|' + name + '#' AS [field/values/value]
FOR XML PATH('fields'),TYPE
)
FROM @tbl AS tbl
FOR XML PATH('record'),ROOT('records')
) AS NVARCHAR(MAX)),'|','<![CDATA['),'#',']]>')
在您将其转换回 XML
的那一刻,CDATA 消失了 :-(
类似的东西
declare @t table (id varchar(10))
insert into @t values ('1')
insert into @t values ('2')
select (
select
t.id 'fields/field/@id'
, t.id 'fields/field/name'
from @t t
for xml path(''), type
) 'records/record'
for xml path('')
我最后用的SQL是:
SELECT TOP 2
(
SELECT
(SELECT 'id' AS [field/@id],
product_id [field/values/value]
FOR XML PATH(''), TYPE),
(SELECT 'title' AS [field/@id],
title [field/values/value]
FOR XML PATH(''), TYPE)
FOR XML PATH('fields'), TYPE
)
FROM products
FOR XML PATH('record'), ROOT('records')
因为这让我可以更轻松地操作输出。
感谢@xdd,尤其是@Shnugo 的回答!最终的解决方案是基于@Shnugo 的建议,只是避免了插入额外空白行的技巧。