我有一张桌子:
with XMLData as (
SELECT uid, commonname, cast(labeldetails as XML) labelxml
FROM [MyLables]
)
SELECT
uid
,commonname
,labelxml
FROM
XMLData [x]
我得到了(为了简洁起见):
B8A3DF5E OrderType1 <NewDataSet><LabelData><Name>1d Vert</Name><Column>...
9D0F94C7 OrderType2 <NewDataSet><LabelData><Name>ItemNumber1D</Name><Co...
内部标签详细信息是XML数据
<NewDataSet>
<LabelData>
<Name>mol</Name>
<Column>mol</Column>
<Type>MOLIMAGE</Type>
<xpos>510</xpos>
<ypos>110</ypos>
<width>auto</width>
<height>auto</height>
<Font>Arial</Font>
<Fontsize>10.0</Fontsize>
<FontStyle>Normal</FontStyle>
<Caption />
<_x0032_DBarcode_Margin>1</_x0032_DBarcode_Margin>
<_x0032_DBarcode_ModSize>5</_x0032_DBarcode_ModSize>
<MOL_WIDTH>200</MOL_WIDTH>
<MOL_HEIGHT>200</MOL_HEIGHT>
<_x0020_MOL_MARGIN>15</_x0020_MOL_MARGIN>
<MOL_BONDLINEWIDTH>2</MOL_BONDLINEWIDTH>
<MOL_BONDSPACEING>5</MOL_BONDSPACEING>
<MOL_FONTSIZE>15</MOL_FONTSIZE>
<xpos_Inches>150</xpos_Inches>
<ypos_Inches>600</ypos_Inches>
<width_Inches>110</width_Inches>
<height_Inches>510</height_Inches>
<LogoImageName>110</LogoImageName>
<ypos_int>110</ypos_int>
<xpos_int>510</xpos_int>
</LabelData>
....
....
</NewDataSet>
我想将LabelDetails转换为XML并创建一个具有各行的临时表:
uid commonname id name column type xpos ypox ...
1234 OrderType1 1 col col TEXT 5 5 ...
1234 OrderType1 2 mol mol MOLIMAGE 1 1 ...
6789 OrderType2 1 col col TEXT 5 5 ...
我不认为所有XML表都有相同的行...假设不是
我已经查看了其他To / From XML问题,其中没有一个看起来合适,我有点不知道下一步该去哪里......
最终,我希望转换为/从XML数据转换,目标是将其作为我们的“系统”存储此数据的旧方式与新方法之间的“间隙”。
我在哪里可以开始创建2个存储过程:FromXMLtoTable和FromTableToXML
答案 0 :(得分:2)
这将帮助您入门。我不得不做类似的事情。这可能不是一个确切的答案,但有一些代码可以用来将XML数据提供给SQL表。
--Set tempXML for testing
CREATE TABLE #tempXML(id INT IDENTITY(1,1) PRIMARY KEY, xmlData XML)
INSERT INTO #tempXML(xmlData)
VALUES('<NewDataSet>
<LabelData>
<Name>mol</Name>
<Column>mol</Column>
<Type>MOLIMAGE</Type>
<xpos>510</xpos>
<ypos>110</ypos>
<width>auto</width>
<height>auto</height>
<Font>Arial</Font>
<Fontsize>10.0</Fontsize>
<FontStyle>Normal</FontStyle>
<Caption />
<_x0032_DBarcode_Margin>1</_x0032_DBarcode_Margin>
<_x0032_DBarcode_ModSize>5</_x0032_DBarcode_ModSize>
<MOL_WIDTH>200</MOL_WIDTH>
<MOL_HEIGHT>200</MOL_HEIGHT>
<_x0020_MOL_MARGIN>15</_x0020_MOL_MARGIN>
<MOL_BONDLINEWIDTH>2</MOL_BONDLINEWIDTH>
<MOL_BONDSPACEING>5</MOL_BONDSPACEING>
<MOL_FONTSIZE>15</MOL_FONTSIZE>
<xpos_Inches>150</xpos_Inches>
<ypos_Inches>600</ypos_Inches>
<width_Inches>110</width_Inches>
<height_Inches>510</height_Inches>
<LogoImageName>110</LogoImageName>
<ypos_int>110</ypos_int>
<xpos_int>510</xpos_int>
</LabelData>
</NewDataSet>')
SELECT r.value('Name[1]', 'nvarchar(100)') AS Field1
, r.value('Column[1]', 'nvarchar(100)') AS Field2
, r.value('Type[1]', 'nvarchar(100)') AS Field3
--etc...
FROM #tempXML
CROSS APPLY xmlData.nodes('/NewDataSet/LabelData') AS x(r)
------------------------------------------------------------------------
DECLARE @loopCount INT
DECLARE @recordID INT
DECLARE @columnName NVARCHAR(128)
DECLARE @dataType NVARCHAR(10)
DECLARE @strSQL NVARCHAR(MAX)
DECLARE @fieldValue NVARCHAR(MAX)
--This table will store your Columns from your new table of xml parsed data
CREATE TABLE #TableFields
(
id int not null identity,
COLUMN_NAME NVARCHAR(100),
DATA_TYPE NVARCHAR(10)
)
--Insert column names from xml parsed data to TableFields temp table
INSERT INTO #TableFields (COLUMN_NAME, DATA_TYPE)
SELECT COLUMN_NAME, DATA_TYPE
FROM Information_Schema.Columns
WHERE Table_Name = 'Insert Table Here'
AND COLUMN_NAME <> 'ID'
--Create your xml parsed table(or use a physical one)
CREATE TABLE #temptable
(
id INT IDENTITY(1,1),
field1 VARCHAR(100),
field2 VARCHAR(100),
field3 VARCHAR(100)
--etc...
)
--Insert the parsed xml from #tempXML test table to #tempTable
INSERT INTO #temptable(fieldName, fieldValue, xmlID)
SELECT r.value('Name[1]', 'nvarchar(100)') AS Field1
, r.value('Column[1]', 'nvarchar(100)') AS Field2
, r.value('Type[1]', 'nvarchar(100)') AS Field3
--etc...
FROM #tempXML
CROSS APPLY xmlData.nodes('/NewDataSet/LabelData') AS x(r)
--Set a loopCount for while loop
SET @loopCount = 1
--Use the while loop to check if we have any fields left to go through
while ( exists(SELECT id FROM #TableFields WHERE id = @loopCount) )
BEGIN
--Get current record in temp table
SELECT @columnName = t.COLUMN_NAME,
@dataType = t.DATA_TYPE,
@fieldValue = v.fieldValue,
@recordID = v.xmlID
FROM #TableFields t
JOIN #temptable v ON
t.id = v.id AND
t.COLUMN_NAME = v.fieldName
WHERE t.id = @loopCount
-----------------------------------------------------------
SET @strSQL = 'UPDATE [insert your table here] SET ' + @columnName + ' = ''' + CONVERT(NVARCHAR(MAX), @fieldValue) + ''' FROM [insert your table here] WHERE ID = ' + CONVERT(NVARCHAR(MAX), @recordID)
EXEC sp_executesql @strSQL, N'@columnName varchar(128)', @columnName = @columnName
DELETE FROM #TableFields WHERE id = @loopCount
SET @loopCount = @loopCount + 1
END
DROP TABLE #TableFields
DROP TABLE #temptable
DROP TABLE #tempXML
答案 1 :(得分:0)
以您描述的方式获取XML非常简单:
SELECT * FROM AnySource FOR XML RAW(N'LabelData'),ELEMENTS,ROOT(N'NewDataSet')
这适用于任何表,视图或表值函数...
如果你的目标是 entity-key-value tupel,那么读取一个未知的XML很容易:
DECLARE @xml XML=
N'<NewDataSet>
<LabelData>
<Name>mol</Name>
<Column>mol</Column>
<Type>MOLIMAGE</Type>
<!--More elements-->
<TEST1>Only existing in 1</TEST1>
</LabelData>
<LabelData>
<Name>2nd name</Name>
<Column>2nd col</Column>
<Type>2nd type</Type>
<!--More elements-->
<TEST2>Only existing in 2</TEST2>
</LabelData>
</NewDataSet>';
WITH NewDataSet aS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS OrdPosition
,ld.query('./*') AS LabelDataElements
FROM @xml.nodes(N'/NewDataSet/LabelData') AS A(ld)
)
SELECT ds.OrdPosition
,AllNodes.value(N'local-name(.)',N'nvarchar(max)') AS ElementName
,AllNodes.value(N'(./text())[1]',N'nvarchar(max)') AS ElementValue
FROM NewDataSet AS ds
CROSS APPLY ds.LabelDataElements.nodes(N'*') AS A(AllNodes);
结果
+-------------+-------------+--------------------+
| OrdPosition | ElementName | ElementValue |
+-------------+-------------+--------------------+
| 1 | Name | mol |
+-------------+-------------+--------------------+
| 1 | Column | mol |
+-------------+-------------+--------------------+
| 1 | Type | MOLIMAGE |
+-------------+-------------+--------------------+
| 1 | TEST1 | Only existing in 1 |
+-------------+-------------+--------------------+
| 2 | Name | 2nd name |
+-------------+-------------+--------------------+
| 2 | Column | 2nd col |
+-------------+-------------+--------------------+
| 2 | Type | 2nd type |
+-------------+-------------+--------------------+
| 2 | TEST2 | Only existing in 2 |
+-------------+-------------+--------------------+
但是将其写入以local-name()
作为列标题的表中更为棘手。有两种情况:
一个很大的优势:您 - 可能 - 了解数据类型,您可以正确读取/转换所有值!
列命名可以使用PIVOT
或分组聚合完成,有大量示例可供查找...
使用SELECT ... INTO SomeStagingTable FROM ...
即时创建表格。
在这种情况下,我会坚持使用 entity-key-value tupels列表。您可以将动态创建的SQL用于动态定义的PIVOT
方法(很多示例!),但这在以后的查询中很难使用。在物理表中没有多大意义,你不知道结构...