SQL 服务器网站 XML 到 table
SQL Server web XML to table
我想从网络中获取数据 XML URL 并将结果转换为具有值的标准 table。
我有以下代码:
IF OBJECT_ID('tempdb..#xml') IS NOT NULL
DROP TABLE #xml
CREATE TABLE #xml (yourXML XML)
GO
DECLARE @URL NVARCHAR(max)
SELECT @URL = 'https://www.boi.org.il/currency.xml'
DECLARE @Response varchar(8000)
DECLARE @XML xml
DECLARE @Obj int
DECLARE @Result int
DECLARE @HTTPStatus int
DECLARE @ErrorMsg varchar(MAX)
EXEC @Result = sp_OACreate 'MSXML2.XMLHttp', @Obj OUT
EXEC @Result = sp_OAMethod @Obj, 'open', NULL, 'GET', @URL, false
EXEC @Result = sp_OAMethod @Obj, 'setRequestHeader', NULL, 'Content-Type', 'application/x-www-form-urlencoded'
EXEC @Result = sp_OAMethod @Obj, send, NULL, ''
EXEC @Result = sp_OAGetProperty @Obj, 'status', @HTTPStatus OUT
INSERT #xml ( yourXML )
EXEC @Result = sp_OAGetProperty @Obj, 'responseXML.xml'--, @Response OUT
SELECT x.*, y.c.query('.')
FROM #xml x
CROSS APPLY x.yourXML.nodes('/CURRENCIES/CURRENCY') y(c)
现在这段代码的结果是一个 XML“超链接”查询,我想将它作为标准值查询结果,最终我可以使用这些数据。
查询结果结构列应该是:
LAST_UPDATE | NAME | UNIT | CURRENCYCODE | RATE
我强烈建议你不要从 T-SQL 发出网络请求,这不是它的地方。在 Powershell、C# 或 Java 中执行,在 SQL 服务器外部。
SQL 服务器未设计为有额外的线程等待网络请求。在 sp_oa
函数中调试错误也非常困难。
此外,这些功能存在诸多问题,尤其是多年未更新,疑似存在安全问题。似乎对于要保持安全的数据库服务器来说,最糟糕的事情之一就是让它“上网冲浪”。
另请参阅以下内容以获取更多信息:
How to avoid sp_OACreate limits?
sp_OACreate error on SQL Server 2005
When did sp_OACreate et. al. become deprecated?
加载后SQL中的XML仍然可以解析,方法如下:
使用/text()
获取节点的内部文本,比只使用节点名更快。确保数据类型符合您的要求。
SELECT
x.yourXML.value('(/CURRENCIES/LAST_UPDATE/text())[1]','date') Last_Update,
n.c.value('(/NAME/text())[1]','nvarchar(50)') Name,
n.c.value('(/UNIT/text())[1]','decimal(18,10)') Unit,
n.c.value('(/CURRENCYCODE/text())[1]','nchar(3)') CurrencyCode,
n.c.value('(/RATE/text())[1]','decimal(18,10)') Rate
FROM #xml x
CROSS APPLY x.yourXML.nodes('/CURRENCIES/CURRENCY') n(c);
你的结果:
EXEC @Result = sp_OAMethod @Obj, 'close';--, NULL, 'GET', @URL, false
SELECT d.value('(./LAST_UPDATE)[1]', 'DATETIME') AS LAST_UPDATE,
c.value('(./NAME)[1]', 'NVARCHAR(64)') AS NAME,
c.value('(./UNIT)[1]', 'SMALLINT') AS UNIT,
c.value('(./CURRENCYCODE )[1]', 'NVARCHAR(64)') AS CURRENCYCODE,
c.value('(./RATE)[1]', 'DECIMAL(38,2)') AS RATE
FROM #xml x
CROSS APPLY x.yourXML.nodes('/CURRENCIES/CURRENCY') y(c)
CROSS APPLY x.yourXML.nodes('/CURRENCIES') z(d);
不要忘记关闭您的 OA 对象。
并最终禁用使用它的可能性:
EXEC sp_configure 'Ole Automation Procedures', 0;
RECONFIGURE;
当然,我更喜欢这个带有 table 变量的版本:
DECLARE @vxml TABLE (an_xml XML);
DECLARE @URL NVARCHAR(max) = 'https://www.boi.org.il/currency.xml',
@Obj int,
@Result int,
@HTTPStatus int;
EXEC sp_configure 'Ole Automation Procedures', 1;
RECONFIGURE;
EXEC @Result = sp_OACreate 'MSXML2.XMLHttp', @Obj OUT;
EXEC @Result = sp_OAMethod @Obj, 'open', NULL, 'GET', @URL, false;
EXEC @Result = sp_OAMethod @Obj, 'setRequestHeader', NULL, 'Content-Type', 'application/x-www-form-urlencoded';
EXEC @Result = sp_OAMethod @Obj, send, NULL, '';
EXEC @Result = sp_OAGetProperty @Obj, 'status', @HTTPStatus OUT;
INSERT @vxml ( an_xml )
EXEC @Result = sp_OAGetProperty @Obj, 'responseXML.xml';
EXEC @Result = sp_OAMethod @Obj, 'close';
EXEC sp_configure 'Ole Automation Procedures',0;
RECONFIGURE;
SELECT d.value('(./LAST_UPDATE)[1]', 'DATETIME') AS LAST_UPDATE,
c.value('(./NAME)[1]', 'NVARCHAR(64)') AS NAME,
c.value('(./UNIT)[1]', 'SMALLINT') AS UNIT,
c.value('(./CURRENCYCODE )[1]', 'NVARCHAR(64)') AS CURRENCYCODE,
c.value('(./RATE)[1]', 'DECIMAL(38,2)') AS RATE
FROM @vxml AS x
CROSS APPLY x.an_xml.nodes('/CURRENCIES/CURRENCY') y(c)
CROSS APPLY x.an_xml.nodes('/CURRENCIES') z(d);
我想从网络中获取数据 XML URL 并将结果转换为具有值的标准 table。
我有以下代码:
IF OBJECT_ID('tempdb..#xml') IS NOT NULL
DROP TABLE #xml
CREATE TABLE #xml (yourXML XML)
GO
DECLARE @URL NVARCHAR(max)
SELECT @URL = 'https://www.boi.org.il/currency.xml'
DECLARE @Response varchar(8000)
DECLARE @XML xml
DECLARE @Obj int
DECLARE @Result int
DECLARE @HTTPStatus int
DECLARE @ErrorMsg varchar(MAX)
EXEC @Result = sp_OACreate 'MSXML2.XMLHttp', @Obj OUT
EXEC @Result = sp_OAMethod @Obj, 'open', NULL, 'GET', @URL, false
EXEC @Result = sp_OAMethod @Obj, 'setRequestHeader', NULL, 'Content-Type', 'application/x-www-form-urlencoded'
EXEC @Result = sp_OAMethod @Obj, send, NULL, ''
EXEC @Result = sp_OAGetProperty @Obj, 'status', @HTTPStatus OUT
INSERT #xml ( yourXML )
EXEC @Result = sp_OAGetProperty @Obj, 'responseXML.xml'--, @Response OUT
SELECT x.*, y.c.query('.')
FROM #xml x
CROSS APPLY x.yourXML.nodes('/CURRENCIES/CURRENCY') y(c)
现在这段代码的结果是一个 XML“超链接”查询,我想将它作为标准值查询结果,最终我可以使用这些数据。
查询结果结构列应该是:
LAST_UPDATE | NAME | UNIT | CURRENCYCODE | RATE
我强烈建议你不要从 T-SQL 发出网络请求,这不是它的地方。在 Powershell、C# 或 Java 中执行,在 SQL 服务器外部。
SQL 服务器未设计为有额外的线程等待网络请求。在 sp_oa
函数中调试错误也非常困难。
此外,这些功能存在诸多问题,尤其是多年未更新,疑似存在安全问题。似乎对于要保持安全的数据库服务器来说,最糟糕的事情之一就是让它“上网冲浪”。
另请参阅以下内容以获取更多信息:
How to avoid sp_OACreate limits?
sp_OACreate error on SQL Server 2005
When did sp_OACreate et. al. become deprecated?
加载后SQL中的XML仍然可以解析,方法如下:
使用/text()
获取节点的内部文本,比只使用节点名更快。确保数据类型符合您的要求。
SELECT
x.yourXML.value('(/CURRENCIES/LAST_UPDATE/text())[1]','date') Last_Update,
n.c.value('(/NAME/text())[1]','nvarchar(50)') Name,
n.c.value('(/UNIT/text())[1]','decimal(18,10)') Unit,
n.c.value('(/CURRENCYCODE/text())[1]','nchar(3)') CurrencyCode,
n.c.value('(/RATE/text())[1]','decimal(18,10)') Rate
FROM #xml x
CROSS APPLY x.yourXML.nodes('/CURRENCIES/CURRENCY') n(c);
你的结果:
EXEC @Result = sp_OAMethod @Obj, 'close';--, NULL, 'GET', @URL, false
SELECT d.value('(./LAST_UPDATE)[1]', 'DATETIME') AS LAST_UPDATE,
c.value('(./NAME)[1]', 'NVARCHAR(64)') AS NAME,
c.value('(./UNIT)[1]', 'SMALLINT') AS UNIT,
c.value('(./CURRENCYCODE )[1]', 'NVARCHAR(64)') AS CURRENCYCODE,
c.value('(./RATE)[1]', 'DECIMAL(38,2)') AS RATE
FROM #xml x
CROSS APPLY x.yourXML.nodes('/CURRENCIES/CURRENCY') y(c)
CROSS APPLY x.yourXML.nodes('/CURRENCIES') z(d);
不要忘记关闭您的 OA 对象。 并最终禁用使用它的可能性:
EXEC sp_configure 'Ole Automation Procedures', 0;
RECONFIGURE;
当然,我更喜欢这个带有 table 变量的版本:
DECLARE @vxml TABLE (an_xml XML);
DECLARE @URL NVARCHAR(max) = 'https://www.boi.org.il/currency.xml',
@Obj int,
@Result int,
@HTTPStatus int;
EXEC sp_configure 'Ole Automation Procedures', 1;
RECONFIGURE;
EXEC @Result = sp_OACreate 'MSXML2.XMLHttp', @Obj OUT;
EXEC @Result = sp_OAMethod @Obj, 'open', NULL, 'GET', @URL, false;
EXEC @Result = sp_OAMethod @Obj, 'setRequestHeader', NULL, 'Content-Type', 'application/x-www-form-urlencoded';
EXEC @Result = sp_OAMethod @Obj, send, NULL, '';
EXEC @Result = sp_OAGetProperty @Obj, 'status', @HTTPStatus OUT;
INSERT @vxml ( an_xml )
EXEC @Result = sp_OAGetProperty @Obj, 'responseXML.xml';
EXEC @Result = sp_OAMethod @Obj, 'close';
EXEC sp_configure 'Ole Automation Procedures',0;
RECONFIGURE;
SELECT d.value('(./LAST_UPDATE)[1]', 'DATETIME') AS LAST_UPDATE,
c.value('(./NAME)[1]', 'NVARCHAR(64)') AS NAME,
c.value('(./UNIT)[1]', 'SMALLINT') AS UNIT,
c.value('(./CURRENCYCODE )[1]', 'NVARCHAR(64)') AS CURRENCYCODE,
c.value('(./RATE)[1]', 'DECIMAL(38,2)') AS RATE
FROM @vxml AS x
CROSS APPLY x.an_xml.nodes('/CURRENCIES/CURRENCY') y(c)
CROSS APPLY x.an_xml.nodes('/CURRENCIES') z(d);