【问题标题】:SQL Server web XML to tableSQL Server Web XML 到表
【发布时间】:2021-05-30 01:59:25
【问题描述】:

我想从 Web XML URL 获取数据并将结果转换为带有值的标准表。

我有以下代码:

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

【问题讨论】:

    标签: sql sql-server xml tsql xml-parsing


    【解决方案1】:

    我强烈建议您不要从 T-SQL 发出 Web 请求,它不适合它。在 SQL Server 外部的 Powershell、C# 或 Java 中执行此操作。

    SQL Server 的设计初衷不是让额外的线程等待 Web 请求。在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);
    

    【讨论】:

    • 为什么不推荐这种方法?
    【解决方案2】:

    为了你的结果:

    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;
    

    当然我更喜欢这个带有表变量的版本:

    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);
    

    【讨论】:

      猜你喜欢
      • 2016-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-07
      • 2017-01-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多