SQL 服务器 - XML 加载问题
SQL Server - XML Load Issue
'嗨,我正在尝试创建自动 XML 加载到 SQL 中,最初我需要使用正确的数据集创建 table。最后,我试图获取序列号、IP 地址和时区以及 "From to " 到“时间戳”的所有计数值这是我的 XML 的样子:
<response xmlns="http://www.test.com/sensor-api/v2">
<sensor-time timezone="America/New_York">2017-07-18T15:45:03-04:00</sensor-time>
<status>
<code>OK</code>
</status>
<sensor-info>
<serial-number>Q8:80:39:60:9Z:F2</serial-number>
<ip-address>192.167.130.18</ip-address>
<name>Test</name>
<group />
<device-type>PC2 - UL</device-type>
</sensor-info>
<content>
<elements>
<element>
<element-id>2</element-id>
<element-name>Conf_Lower_Zone</element-name>
<sensor-type>SINGLE_SENSOR</sensor-type>
<data-type>ZONE</data-type>
<from>2017-07-18T15:40:00-04:00</from>
<to>2017-07-18T15:45:00-04:00</to>
<resolution>ONE_MINUTE</resolution>
<measurements>
<measurement>
<from>2017-07-18T15:40:00-04:00</from>
<to>2017-07-18T15:41:00-04:00</to>
<values>
<value label="count">0</value>
</values>
</measurement>
<measurement>
<from>2017-07-18T15:41:00-04:00</from>
<to>2017-07-18T15:42:00-04:00</to>
<values>
<value label="count">0</value>
</values>
</measurement>
这是我的 SQL 部分:
CREATE DATABASE OPENXMLTesting
GO
USE OPENXMLTesting
GO
CREATE TABLE XMLwithOpenXML
(
Id INT IDENTITY PRIMARY KEY,
XMLData XML,
LoadedDateTime DATETIME
)
INSERT INTO XMLwithOpenXML(XMLData, LoadedDateTime)
SELECT CONVERT(XML, BulkColumn) AS BulkColumn, GETDATE()
FROM OPENROWSET(BULK 'C:\Example\Test.xml', SINGLE_BLOB) AS x;
SELECT * FROM XMLwithOpenXML
USE OPENXMLTesting
GO
DECLARE @XML AS XML, @hDoc AS INT, @SQL NVARCHAR (MAX)
SELECT @XML = XMLData FROM XMLwithOpenXML
EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML
SELECT [element-id], [element-name], [data-type], [ip-address]
FROM OPENXML(@hDoc,
'content/elements/element/measurements/measurement/values/value')
WITH
(
[element-id] varchar (100) '@ElementID',
[element-name] varchar(50) '@Element_Name',
[data-type] varchar(50) '@Data_Type',
[ip-address] varchar(50) '@IP_Address'
)
EXEC sp_xml_removedocument @hDoc
GO
问题是我得到的结果是 headers,下面没有任何数据。见下图。
我做错了什么?
有两个问题...
首先涉及到命名空间。因为它是默认命名空间,所以您必须声明或使用通配符。
其次,选择的方法 FROM OPENXML
与两个存储过程一起创建和删除文档已经完全过时了。您应该使用现代原生 XML 方法。试试这个:
DECLARE @xml XML=
N'<response xmlns="http://www.test.com/sensor-api/v2">
<sensor-time timezone="America/New_York">2017-07-18T15:45:03-04:00</sensor-time>
<status>
<code>OK</code>
</status>
<sensor-info>
<serial-number>Q8:80:39:60:9Z:F2</serial-number>
<ip-address>192.167.130.18</ip-address>
<name>Test</name>
<group />
<device-type>PC2 - UL</device-type>
</sensor-info>
<content>
<elements>
<element>
<element-id>2</element-id>
<element-name>Conf_Lower_Zone</element-name>
<sensor-type>SINGLE_SENSOR</sensor-type>
<data-type>ZONE</data-type>
<from>2017-07-18T15:40:00-04:00</from>
<to>2017-07-18T15:45:00-04:00</to>
<resolution>ONE_MINUTE</resolution>
<measurements>
<measurement>
<from>2017-07-18T15:40:00-04:00</from>
<to>2017-07-18T15:41:00-04:00</to>
<values>
<value label="count">0</value>
</values>
</measurement>
<measurement>
<from>2017-07-18T15:41:00-04:00</from>
<to>2017-07-18T15:42:00-04:00</to>
<values>
<value label="count">0</value>
</values>
</measurement>
</measurements>
</element>
</elements>
</content>
</response>';
--查询需要声明命名空间
--我将使用直接调用来获取奇异值
--...和 .nodes()
以获得一组 1:n
相关元素
WITH XMLNAMESPACES(DEFAULT 'http://www.test.com/sensor-api/v2')
SELECT @xml.value('(/response/sensor-time/@timezone)[1]','nvarchar(max)') AS SensortTime_TimeZone
,@xml.value('(/response/sensor-time/text())[1]','datetime') AS SensortTime
,@xml.value('(/response/status/code/text())[1]','nvarchar(max)') AS StatusCode
,@xml.value('(/response/sensor-info/serial-number/text())[1]','nvarchar(max)') AS SerialNumber
,e.value('(element-id/text())[1]','int') AS ElementId
,e.value('(element-name/text())[1]','nvarchar(max)') AS ElementName
--more from here
,m.value('(from/text())[1]','datetime') AS Measurement_From
,m.value('(to/text())[1]','datetime') AS Measurement_To
,m.value('(values/value/@label)[1]','nvarchar(max)') AS Measurement_Label
,m.value('(values/value/text())[1]','int') AS Measurement_Label
FROM @xml.nodes('/response/content/elements/element') A(e)
OUTER APPLY e.nodes('measurements/measurement') B(m);
'嗨,我正在尝试创建自动 XML 加载到 SQL 中,最初我需要使用正确的数据集创建 table。最后,我试图获取序列号、IP 地址和时区以及 "From to " 到“时间戳”的所有计数值这是我的 XML 的样子:
<response xmlns="http://www.test.com/sensor-api/v2">
<sensor-time timezone="America/New_York">2017-07-18T15:45:03-04:00</sensor-time>
<status>
<code>OK</code>
</status>
<sensor-info>
<serial-number>Q8:80:39:60:9Z:F2</serial-number>
<ip-address>192.167.130.18</ip-address>
<name>Test</name>
<group />
<device-type>PC2 - UL</device-type>
</sensor-info>
<content>
<elements>
<element>
<element-id>2</element-id>
<element-name>Conf_Lower_Zone</element-name>
<sensor-type>SINGLE_SENSOR</sensor-type>
<data-type>ZONE</data-type>
<from>2017-07-18T15:40:00-04:00</from>
<to>2017-07-18T15:45:00-04:00</to>
<resolution>ONE_MINUTE</resolution>
<measurements>
<measurement>
<from>2017-07-18T15:40:00-04:00</from>
<to>2017-07-18T15:41:00-04:00</to>
<values>
<value label="count">0</value>
</values>
</measurement>
<measurement>
<from>2017-07-18T15:41:00-04:00</from>
<to>2017-07-18T15:42:00-04:00</to>
<values>
<value label="count">0</value>
</values>
</measurement>
这是我的 SQL 部分:
CREATE DATABASE OPENXMLTesting
GO
USE OPENXMLTesting
GO
CREATE TABLE XMLwithOpenXML
(
Id INT IDENTITY PRIMARY KEY,
XMLData XML,
LoadedDateTime DATETIME
)
INSERT INTO XMLwithOpenXML(XMLData, LoadedDateTime)
SELECT CONVERT(XML, BulkColumn) AS BulkColumn, GETDATE()
FROM OPENROWSET(BULK 'C:\Example\Test.xml', SINGLE_BLOB) AS x;
SELECT * FROM XMLwithOpenXML
USE OPENXMLTesting
GO
DECLARE @XML AS XML, @hDoc AS INT, @SQL NVARCHAR (MAX)
SELECT @XML = XMLData FROM XMLwithOpenXML
EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML
SELECT [element-id], [element-name], [data-type], [ip-address]
FROM OPENXML(@hDoc,
'content/elements/element/measurements/measurement/values/value')
WITH
(
[element-id] varchar (100) '@ElementID',
[element-name] varchar(50) '@Element_Name',
[data-type] varchar(50) '@Data_Type',
[ip-address] varchar(50) '@IP_Address'
)
EXEC sp_xml_removedocument @hDoc
GO
问题是我得到的结果是 headers,下面没有任何数据。见下图。
我做错了什么?
有两个问题...
首先涉及到命名空间。因为它是默认命名空间,所以您必须声明或使用通配符。
其次,选择的方法 FROM OPENXML
与两个存储过程一起创建和删除文档已经完全过时了。您应该使用现代原生 XML 方法。试试这个:
DECLARE @xml XML=
N'<response xmlns="http://www.test.com/sensor-api/v2">
<sensor-time timezone="America/New_York">2017-07-18T15:45:03-04:00</sensor-time>
<status>
<code>OK</code>
</status>
<sensor-info>
<serial-number>Q8:80:39:60:9Z:F2</serial-number>
<ip-address>192.167.130.18</ip-address>
<name>Test</name>
<group />
<device-type>PC2 - UL</device-type>
</sensor-info>
<content>
<elements>
<element>
<element-id>2</element-id>
<element-name>Conf_Lower_Zone</element-name>
<sensor-type>SINGLE_SENSOR</sensor-type>
<data-type>ZONE</data-type>
<from>2017-07-18T15:40:00-04:00</from>
<to>2017-07-18T15:45:00-04:00</to>
<resolution>ONE_MINUTE</resolution>
<measurements>
<measurement>
<from>2017-07-18T15:40:00-04:00</from>
<to>2017-07-18T15:41:00-04:00</to>
<values>
<value label="count">0</value>
</values>
</measurement>
<measurement>
<from>2017-07-18T15:41:00-04:00</from>
<to>2017-07-18T15:42:00-04:00</to>
<values>
<value label="count">0</value>
</values>
</measurement>
</measurements>
</element>
</elements>
</content>
</response>';
--查询需要声明命名空间
--我将使用直接调用来获取奇异值
--...和 .nodes()
以获得一组 1:n
相关元素
WITH XMLNAMESPACES(DEFAULT 'http://www.test.com/sensor-api/v2')
SELECT @xml.value('(/response/sensor-time/@timezone)[1]','nvarchar(max)') AS SensortTime_TimeZone
,@xml.value('(/response/sensor-time/text())[1]','datetime') AS SensortTime
,@xml.value('(/response/status/code/text())[1]','nvarchar(max)') AS StatusCode
,@xml.value('(/response/sensor-info/serial-number/text())[1]','nvarchar(max)') AS SerialNumber
,e.value('(element-id/text())[1]','int') AS ElementId
,e.value('(element-name/text())[1]','nvarchar(max)') AS ElementName
--more from here
,m.value('(from/text())[1]','datetime') AS Measurement_From
,m.value('(to/text())[1]','datetime') AS Measurement_To
,m.value('(values/value/@label)[1]','nvarchar(max)') AS Measurement_Label
,m.value('(values/value/text())[1]','int') AS Measurement_Label
FROM @xml.nodes('/response/content/elements/element') A(e)
OUTER APPLY e.nodes('measurements/measurement') B(m);