SQL 服务器 XML
SQL Server FOR XML
我在 SQL 服务器中有一个 table,它看起来与任何其他 table 一样,具有以下列名:
primaryID | column1 | column2 | column3| column4 | column5
我需要获取 table 中的不同字段并按以下格式创建 XML:
<Record>
<Field id="column1" value="ABCDEFG" />
<Field id="column2" value="Some text" />
<Field id="column3" value="Some other text" />
<Field id="column4" value="myValue" />
<Field id="column5" value="88" />
</Record>
在这种情况下,节点是为 table 中的每条记录创建的。该节点针对该特定记录的每一列完成。
我已经尝试了所有可能的 RAW、PATH、ROOT 和 EXPLICIT 组合,但都无济于事。
我的提议甚至可以在 SQL 服务器中实现,还是我需要在其他地方实现?
您必须指定 xml 路径以获取您想要的节点。
这是一个基于您的示例的示例:
CREATE TABLE #temp (primaryid INT, column1 VARCHAR(50), column2 VARCHAR(50), column3 VARCHAR(50) )
INSERT INTO #Temp (primaryid, column1, column2, column3 ) VALUES (0, 'abc0', 'some text0', 'myvalue0')
INSERT INTO #Temp (primaryid, column1, column2, column3 ) VALUES (1, 'abc1', 'some text1', 'myvalue1')
SELECT '',
(
SELECT
'column1' AS '@id',
column1 AS '@value'
FROM #temp a
WHERE a.primaryid = #temp.primaryid
FOR XML PATH('Field'), TYPE
),
(
SELECT
'column2' AS '@id',
column2 AS '@value'
FROM #temp a
WHERE a.primaryid = #temp.primaryid
FOR XML PATH('Field'), TYPE
),
(
SELECT
'column3' AS '@id',
column3 AS '@value'
FROM #temp a
WHERE a.primaryid = #temp.primaryid
FOR XML PATH('Field'), TYPE
)
from #Temp
FOR XML PATH('Record'), TYPE
DROP TABLE #temp
上面的例子产生了这样的结果:
<Record>
<Field id="column1" value="abc0" />
<Field id="column2" value="some text0" />
<Field id="column3" value="myvalue0" />
</Record>
<Record>
<Field id="column1" value="abc1" />
<Field id="column2" value="some text1" />
<Field id="column3" value="myvalue1" />
</Record>
虽然@Avitus 的回答给了你你需要的结果,但在软件开发中,它不仅与结果有关,还与代码的可读性和可维护性有关。所以我决定给你更多的选择:
如果您不介意明确指定列名,这里有一个简单的解决方案 select ... for xml
:
1.1。 select ... 对于 xml 自动
select
(
select *
from (values
('column1', column1),
('column2', column2),
('column3', column3)
) as Field(id, value)
for xml auto, type
)
from <Table> as Record
for xml auto
1.2。 select ... 对于 xml 原始
select
(
select *
from (values
('column1', column1),
('column2', column2),
('column3', column3)
) as Field(id, value)
for xml raw('Field'), type
)
from <Table>
for xml raw('Record')
1.3。 select ... 对于 xml 路径
select
(
select *
from (values
('column1', column1),
('column2', column2),
('column3', column3)
) as a([@id], [@value])
for xml path('Field'), type
)
from <Table>
for xml path('Record')
更通用的解决方案 - 这些解决方案允许您仅指定您不想在结果中看到的列:
2.1。上面的任何解决方案都包含在动态 SQL
中
declare @stmt nvarchar(max)
select @stmt = isnull(@stmt + ',','') + '(''' + name + ''', ' + name + ')'
from sys.columns
where
[object_id] = object_id('<Table>') and
name not in ('primaryid')
select @stmt = '
select
(
select *
from (values ' + @stmt + '
) as Field(id, value)
for xml auto, type
)
from <Table> as Record
for xml auto
'
exec sp_executesql
@stmt = @stmt
2.2 Double select for xml (xml trick)
;with cte_xml as (
select (select a.* for xml raw, type) as data
from #temp as a
)
select
(
select
t.c.value('local-name(.)', 'nvarchar(128)') as [@id],
t.c.value('.', 'nvarchar(128)') as [@value]
from data.nodes('row/@*') as t(c)
where t.c.value('local-name(.)', 'nvarchar(128)') not in ('primaryid')
for xml path('Field'), type
)
from cte_xml
for xml path('Record')
我在 SQL 服务器中有一个 table,它看起来与任何其他 table 一样,具有以下列名:
primaryID | column1 | column2 | column3| column4 | column5
我需要获取 table 中的不同字段并按以下格式创建 XML:
<Record>
<Field id="column1" value="ABCDEFG" />
<Field id="column2" value="Some text" />
<Field id="column3" value="Some other text" />
<Field id="column4" value="myValue" />
<Field id="column5" value="88" />
</Record>
在这种情况下,节点是为 table 中的每条记录创建的。该节点针对该特定记录的每一列完成。 我已经尝试了所有可能的 RAW、PATH、ROOT 和 EXPLICIT 组合,但都无济于事。
我的提议甚至可以在 SQL 服务器中实现,还是我需要在其他地方实现?
您必须指定 xml 路径以获取您想要的节点。
这是一个基于您的示例的示例:
CREATE TABLE #temp (primaryid INT, column1 VARCHAR(50), column2 VARCHAR(50), column3 VARCHAR(50) )
INSERT INTO #Temp (primaryid, column1, column2, column3 ) VALUES (0, 'abc0', 'some text0', 'myvalue0')
INSERT INTO #Temp (primaryid, column1, column2, column3 ) VALUES (1, 'abc1', 'some text1', 'myvalue1')
SELECT '',
(
SELECT
'column1' AS '@id',
column1 AS '@value'
FROM #temp a
WHERE a.primaryid = #temp.primaryid
FOR XML PATH('Field'), TYPE
),
(
SELECT
'column2' AS '@id',
column2 AS '@value'
FROM #temp a
WHERE a.primaryid = #temp.primaryid
FOR XML PATH('Field'), TYPE
),
(
SELECT
'column3' AS '@id',
column3 AS '@value'
FROM #temp a
WHERE a.primaryid = #temp.primaryid
FOR XML PATH('Field'), TYPE
)
from #Temp
FOR XML PATH('Record'), TYPE
DROP TABLE #temp
上面的例子产生了这样的结果:
<Record>
<Field id="column1" value="abc0" />
<Field id="column2" value="some text0" />
<Field id="column3" value="myvalue0" />
</Record>
<Record>
<Field id="column1" value="abc1" />
<Field id="column2" value="some text1" />
<Field id="column3" value="myvalue1" />
</Record>
虽然@Avitus 的回答给了你你需要的结果,但在软件开发中,它不仅与结果有关,还与代码的可读性和可维护性有关。所以我决定给你更多的选择:
如果您不介意明确指定列名,这里有一个简单的解决方案 select ... for xml
:
1.1。 select ... 对于 xml 自动
select
(
select *
from (values
('column1', column1),
('column2', column2),
('column3', column3)
) as Field(id, value)
for xml auto, type
)
from <Table> as Record
for xml auto
1.2。 select ... 对于 xml 原始
select
(
select *
from (values
('column1', column1),
('column2', column2),
('column3', column3)
) as Field(id, value)
for xml raw('Field'), type
)
from <Table>
for xml raw('Record')
1.3。 select ... 对于 xml 路径
select
(
select *
from (values
('column1', column1),
('column2', column2),
('column3', column3)
) as a([@id], [@value])
for xml path('Field'), type
)
from <Table>
for xml path('Record')
更通用的解决方案 - 这些解决方案允许您仅指定您不想在结果中看到的列:
2.1。上面的任何解决方案都包含在动态 SQL
中declare @stmt nvarchar(max)
select @stmt = isnull(@stmt + ',','') + '(''' + name + ''', ' + name + ')'
from sys.columns
where
[object_id] = object_id('<Table>') and
name not in ('primaryid')
select @stmt = '
select
(
select *
from (values ' + @stmt + '
) as Field(id, value)
for xml auto, type
)
from <Table> as Record
for xml auto
'
exec sp_executesql
@stmt = @stmt
2.2 Double select for xml (xml trick)
;with cte_xml as (
select (select a.* for xml raw, type) as data
from #temp as a
)
select
(
select
t.c.value('local-name(.)', 'nvarchar(128)') as [@id],
t.c.value('.', 'nvarchar(128)') as [@value]
from data.nodes('row/@*') as t(c)
where t.c.value('local-name(.)', 'nvarchar(128)') not in ('primaryid')
for xml path('Field'), type
)
from cte_xml
for xml path('Record')