【发布时间】:2010-09-07 04:49:58
【问题描述】:
有没有办法从 TSQL 存储过程或函数调用 Web 服务?
【问题讨论】:
-
同意这不是想做的事,但有时你必须做一些你不喜欢做的事情。在这种情况下,我最终将 Web 服务函数重写为 sql 函数来完成相同的任务。感谢所有链接和建议。
标签: sql-server web-services tsql
有没有办法从 TSQL 存储过程或函数调用 Web 服务?
【问题讨论】:
标签: sql-server web-services tsql
是的,你可以这样创建
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
【讨论】:
当然你可以,但这是一个糟糕的主意。
由于网络服务调用可能需要任意时间,并且随机失败,具体取决于当时您的网络上正在玩的反恐精英游戏的数量,您无法确定这需要多长时间。
在它构建 XML、将 HTTP 请求发送到远程服务器,然后它必须解析 XML 并发送回响应时,您至少需要半秒时间。
无论哪个应用程序执行了导致 Web 服务触发的 INSERT INTO BLAH 查询,都必须等待它完成。除非这是仅在后台发生的事情,例如每日计划任务,否则您的应用的性能将会爆炸
Web 服务调用代码在 SQL Server 内部运行,并耗尽了它的资源。由于等待 HTTP 请求需要很长时间,最终会消耗大量资源,这将再次损害服务器的性能。
【讨论】:
不是在 T-SQL 代码本身中,而是在 SQL Server 2005 及更高版本中,他们启用了编写 CLR 存储过程的能力,这些存储过程本质上是 .NET 代码中的函数,然后将它们公开为存储过程以供使用。大部分 .NET 框架都触手可及,因此我可以看到通过它可以使用 Web 服务。
在这里详细讨论有点冗长,但这里有一个指向MSDN article 的链接。
【讨论】:
我不会为繁重的流量或关键任务的东西这样做,但是,如果您不需要从服务接收反馈,那么这实际上是一件很棒的事情。
这是我所做的一个例子。
不要使用旧的 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
【讨论】:
Exec sp_OADestroy @Object
sp_OA* 调用
在早期版本的 Sql 中,您可以使用扩展存储过程或 xp_cmdshell 来壳和调用 web 服务。
这两种架构听起来都不像一个不错的架构——但有时你必须做一些疯狂的事情。
【讨论】:
您可以使用嵌入的 VB 对象来做到这一点。
首先,您创建一个类型为“MSXML2.XMLHttp”的 VB 对象,然后将这个对象用于所有查询(如果您每次都重新创建它,预计会造成严重的性能损失)。
然后您将该对象和一些参数输入到一个存储过程中,该过程在该对象上调用 sp_OAMethod。
抱歉这个不精确的例子,但是快速谷歌搜索应该会发现 vb-script 方法是如何完成的。
--
但是 CLR 版本要简单得多....要容易得多。 调用 web 服务的问题在于它们无法跟上数据库引擎的步伐。您会遇到很多无法跟上的错误。
请记住,网络服务每次都需要新的连接。多样性开始发挥作用。您不想打开 5000 个套接字连接来为表上的函数调用提供服务。太牛了!
在这种情况下,您必须创建一个自定义聚合函数,并使用 THAT 作为参数传递给您的 Web 服务,这将返回一个结果集......然后您必须整理它。这确实是一种获取数据的尴尬方式。
【讨论】:
这是一个从 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'
【讨论】:
如果您使用 sql 2000 兼容级别并且无法进行 clr 集成,请参阅http://www.vishalseth.com/post/2009/12/22/Call-a-webservice-from-TSQL-(Stored-Procedure)-using-MSXML.aspx
【讨论】:
我一直在为世界各地的大型/跨国公司工作,使用 Oracle 数据库。我们一直在通过带有存储过程的数据库使用 Web 服务,并且没有任何问题,即使是那些流量很大的。所有这些都供内部使用,我的意思是无法访问互联网,只能在工厂内部使用。我会建议使用它,但要非常小心你的设计方式
【讨论】: