【问题标题】:Can you call a webservice from TSQL code?您可以从 SQL 代码调用 Web 服务吗?
【发布时间】:2010-09-07 04:49:58
【问题描述】:

有没有办法从 TSQL 存储过程或函数调用 Web 服务?

【问题讨论】:

  • 同意这不是想做的事,但有时你必须做一些你不喜欢做的事情。在这种情况下,我最终将 Web 服务函数重写为 sql 函数来完成相同的任务。感谢所有链接和建议。

标签: sql-server web-services tsql


【解决方案1】:

是的,你可以这样创建

CREATE PROCEDURE CALLWEBSERVICE(@Para1 ,@Para2)
AS
BEGIN
    Declare @Object as Int;
    Declare @ResponseText as Varchar(8000);

    Exec sp_OACreate 'MSXML2.XMLHTTP', @Object OUT;
    Exec sp_OAMethod @Object, 'open', NULL, 'get', 'http://www.webservicex.com/stockquote.asmx/GetQuote?symbol=MSFT','false'
    Exec sp_OAMethod @Object, 'send'
    Exec sp_OAMethod @Object, 'responseText', @ResponseText OUTPUT
    Select @ResponseText
    Exec sp_OADestroy @Object
END

【讨论】:

  • 如何调用https服务?
  • 不要忘记重新配置 MSSQL 以启用对 Web 服务的调用。请看下面我的回答。我收到错误“SQL Server 阻止访问组件“Ole 自动化过程”的过程“sys.sp_OACreate”,因为该组件作为该服务器安全配置的一部分被关闭。系统管理员可以使用 sp_configure 启用“Ole 自动化过程”的使用。有关启用“Ole 自动化过程”的详细信息,请在 SQL Server 联机丛书中搜索“Ole 自动化过程”。
【解决方案2】:

当然你可以,但这是一个糟糕的主意。

由于网络服务调用可能需要任意时间,并且随机失败,具体取决于当时您的网络上正在玩的反恐精英游戏的数量,您无法确定这需要多长时间。

在它构建 XML、将 HTTP 请求发送到远程服务器,然后它必须解析 XML 并发送回响应时,您至少需要半秒时间。

  1. 无论哪个应用程序执行了导致 Web 服务触发的 INSERT INTO BLAH 查询,都必须等待它完成。除非这是仅在后台发生的事情,例如每日计划任务,否则您的应用的性能将会爆炸

  2. Web 服务调用代码在 SQL Server 内部运行,并耗尽了它的资源。由于等待 HTTP 请求需要很长时间,最终会消耗大量资源,这将再次损害服务器的性能。

【讨论】:

  • +1 表示“取决于当时在您的网络上玩了多少场反恐精英游戏”并且获得了好的答案。 ;)
  • 如果你要说它可以做到,你应该解释一下。
  • 下面的响应者说得很好(在提供了一些有用的线索之后):“并不是说这两个听起来都像一个体面的架构 - 但有时你必须做一些疯狂的事情”。
【解决方案3】:

不是在 T-SQL 代码本身中,而是在 SQL Server 2005 及更高版本中,他们启用了编写 CLR 存储过程的能力,这些存储过程本质上是 .NET 代码中的函数,然后将它们公开为存储过程以供使用。大部分 .NET 框架都触手可及,因此我可以看到通过它可以使用 Web 服务。

在这里详细讨论有点冗长,但这里有一个指向MSDN article 的链接。

【讨论】:

【解决方案4】:

我不会为繁重的流量或关键任务的东西这样做,但是,如果您不需要从服务接收反馈,那么这实际上是一件很棒的事情。

这是我所做的一个例子。

  1. 在表上触发插入和更新
  2. 称为 Stored Proc 的触发器将事务的 JSON 数据传递到 Web Api 端点,然后插入 AWS 中的 MongoDB。

不要使用旧的 XML

JSON

EXEC sp_OACreate 'WinHttp.WinHttpRequest.5.1', @Object OUT;
EXEC sp_OAMethod @Object, 'Open', NULL, 'POST', 'http://server/api/method', 'false'
EXEC sp_OAMethod @Object, 'setRequestHeader', null, 'Content-Type', 'application/json'
DECLARE @len INT = len(@requestBody) 

完整示例:

Alter Procedure yoursprocname

 @WavName varchar(50),
 @Dnis char(4) 

    AS
BEGIN

    SET NOCOUNT ON;


DECLARE @Object INT;
DECLARE @Status INT;


DECLARE @requestBody NVARCHAR(MAX) = '{
"WavName": "{WavName}",
"Dnis": "{Dnis}"
}'


SET @requestBody = REPLACE(@requestBody, '{WavName}', @WavName)
SET @requestBody = REPLACE(@requestBody, '{Dnis}', @Dnis)


EXEC sp_OACreate 'WinHttp.WinHttpRequest.5.1', @Object OUT;
EXEC sp_OAMethod @Object, 'Open', NULL, 'POST',  'http://server/api/method', 'false'
EXEC sp_OAMethod @Object, 'setRequestHeader', null, 'Content-Type', 'application/json'
DECLARE @len INT = len(@requestBody) 
EXEC sp_OAMethod @Object, 'setRequestHeader', null, 'Content-Length', @len
EXEC sp_OAMethod @Object, 'send', null, @requestBody
EXEC sp_OAGetProperty @Object, 'Status', @Status OUT
EXEC sp_OADestroy @Object

【讨论】:

  • 感谢您的示例。您是否还包括@kiran.Backwad 的示例中的Exec sp_OADestroy @Object
  • @TheEmirOfGroofunkistan -- 好的,有完整代码的帖子
  • 有些人转移到 CLR - 这行得通,所以我从不费心替换 sp_OA* 调用
  • 我使用这个脚本,但没有发送到 webservice 。为什么!?
【解决方案5】:

在早期版本的 Sql 中,您可以使用扩展存储过程或 xp_cmdshell 来壳和调用 web 服务。

这两种架构听起来都不像一个不错的架构——但有时你必须做一些疯狂的事情。

【讨论】:

    【解决方案6】:

    您可以使用嵌入的 VB 对象来做到这一点。

    首先,您创建一个类型为“MSXML2.XMLHttp”的 VB 对象,然后将这个对象用于所有查询(如果您每次都重新创建它,预计会造成严重的性能损失)。

    然后您将该对象和一些参数输入到一个存储过程中,该过程在该对象上调用 sp_OAMethod。

    抱歉这个不精确的例子,但是快速谷歌搜索应该会发现 vb-script 方法是如何完成的。

    --

    但是 CLR 版本要简单得多....要容易得多。 调用 web 服务的问题在于它们无法跟上数据库引擎的步伐。您会遇到很多无法跟上的错误。

    请记住,网络服务每次都需要新的连接。多样性开始发挥作用。您不想打开 5000 个套接字连接来为表上的函数调用提供服务。太牛了!

    在这种情况下,您必须创建一个自定义聚合函数,并使用 THAT 作为参数传递给您的 Web 服务,这将返回一个结果集......然后您必须整理它。这确实是一种获取数据的尴尬方式。

    【讨论】:

    • 请记住,使用嵌入式 CLR 往往比使用 OLE 对象执行 MUCH、MUCHMUCH 更好。我有一些小的 CLR 函数,出于客户原因,必须将其转换为调用 OLE。一旦发生这种情况,它的性能就受到了巨大的打击。出于所有意图和目的,立即返回的 CLR 函数突然在每次调用中花费了将近一秒钟的时间返回。
    【解决方案7】:

    这是一个从 Web 服务获取一些数据的示例。在这种情况下,将用户代理字符串解析为 JSON。

    --first configure MSSQL to enable calling out to a webservice (1=true, 0=false)
    sp_configure 'show advanced options', 1;  
    GO  
    RECONFIGURE;  
    GO  
    sp_configure 'Ole Automation Procedures', 1;  
    GO  
    RECONFIGURE;  
    GO  
    
    CREATE PROCEDURE CallWebAPI_ParseUserAgent @UserAgent VARCHAR(512)
    AS
    BEGIN
        SET NOCOUNT ON;
    
        DECLARE @Object INT;
        DECLARE @ResponseText AS VARCHAR(8000);
        DECLARE @url VARCHAR(512)
    
        SET @url = 'http://www.useragentstring.com/?getJSON=all&uas=' + @UserAgent;
    
        EXEC sp_OACreate 'WinHttp.WinHttpRequest.5.1', @Object OUT;
        EXEC sp_OAMethod @Object, 'Open', NULL, 'GET', @url, 'false'
        EXEC sp_OAMethod @Object, 'setRequestHeader', NULL, 'Content-Type', 'application/json'
        EXEC sp_OAMethod @Object, 'send'
        EXEC sp_OAMethod @Object, 'responseText', @ResponseText OUTPUT
        SELECT @ResponseText
        EXEC sp_OADestroy @Object
    END
    
    --example how to call the API
    CallWebAPI_ParseUserAgent 'Mozilla/5.0 (Windows NT 6.2; rv:53.0) Gecko/20100101 Firefox/53.0'
    

    【讨论】:

      【解决方案8】:

      如果您使用 sql 2000 兼容级别并且无法进行 clr 集成,请参阅http://www.vishalseth.com/post/2009/12/22/Call-a-webservice-from-TSQL-(Stored-Procedure)-using-MSXML.aspx

      【讨论】:

        【解决方案9】:

        我一直在为世界各地的大型/跨国公司工作,使用 Oracle 数据库。我们一直在通过带有存储过程的数据库使用 Web 服务,并且没有任何问题,即使是那些流量很大的。所有这些都供内部使用,我的意思是无法访问互联网,只能在工厂内部使用。我会建议使用它,但要非常小心你的设计方式

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多