2014-10-06 117 views
4

我正在尝试在TSQL中构建一个存储过程来调用web服务。我之前在Oracle中做过这个,但是在MSSQL中似乎并不那么容易。 当然有很多原因不会在存储过程中执行此操作,但由于此过程仅用于每日批处理,所以性能不是太大问题。 我想要做的事情如下:发送一个全名到web服务,web服务将返回一个名字,如名字,前缀,姓氏等等。返回的值将需要写入表中。从TSQL存储过程调用SOAP web服务

我发现一个有趣的程序http://www.vishalseth.com/post/2009/12/22/Call-a-webservice-from-TSQL-(Stored-Procedure)-using-MSXML.aspx这似乎正是我想要的,但只要你添加一个正文到调用,我遇到像“参数不正确”的错误。这在文章中也有说明,显然没有简单的解决方案。我绝对需要发送请求主体。

我还阅读了很多关于使用CLI或“Web服务任务编辑器”或“SSIS”解决问题的文章,我找不到有关从何处开始的任何教程。现在我只有Microsoft SQL服务器管理工​​作室。

顺便说一句,我在SQL Server 2012上。

任何关于我应该用这个方向的想法?

我已经发现了这个描述,似乎至极很干净:http://www.databasejournal.com/features/mssql/article.php/3821271/Calling-a-Web-Service-from-within-SQL-Server.htm但是,安装Visual Studio 2012,并创建一个“SQL Server数据库项目”后,我无法选择的解决方案上下文菜单中的“添加Web引用” ,菜单中只有这样的选项。

+0

你得到一个解决方案吗?我目前处于完全相同的情况 – 2015-06-17 13:57:58

回答

4

在我用下面的方法了过去,它可能不是这几天的最佳方法,但它已经成功地为我工作:

DECLARE @obj int, 
     @url VarChar(MAX), 
     @response VarChar(MAX), 
     @requestHeader VarChar(MAX), 
     @requestBody VarChar(MAX) 

SET @url = 'http://....' 

SET @requestBody = '<soapenv:Envelope> 
        <soapenv:Header/> 
         <soapenv:Body> 
         ... 
         </soapenv:Body> 
        </soapenv:Envelope>' 

EXEC sp_OACreate 'MSXML2.ServerXMLHttp', @obj OUT 
EXEC sp_OAMethod @obj, 'Open', NULL, 'GET', @url, false 
EXEC sp_OAMethod @obj, 'setRequestHeader', NULL, 'Content-Type', 'text/xml;charset=UTF-8' 
EXEC sp_OAMethod @obj, 'setRequestHeader', NULL, 'SOAPAction', 'POST' 
EXEC sp_OAMethod @obj, 'setRequestHeader', NULL, 'Content-Length', LEN(@requestBody) 
EXEC sp_OAMethod @obj, 'send', NULL, @requestBody 
EXEC sp_OAGetProperty @obj, 'responseText', @response OUT 


SELECT @response [RESPONSE] 

EXEC sp_OADestroy @obj 

我已经使用这个调用产生报表中的Web服务并在该方法中通过电子邮件发送。

+0

这与我引用的程序中的代码类似。这个代码的问题是你不能发送一个内容体(也就是实际的soap消息)。此方法似乎只适用于REST Web服务。 – ErikL 2014-10-06 13:35:34

+0

我已添加一些修改以显示如何指定请求正文和帖子。 – Mattgb 2014-10-06 15:34:52

+0

抱歉,刚刚查看了您的链接,他们给出了相同的答案,必须是星期一! – Mattgb 2014-10-06 15:40:28

0

在Visual Studio中维护SQL Server项目时,无法以通常方式添加Web引用。但是,您可以使用WSDL实用程序创建Web Interface并将其添加到您的解决方案中。随后,您将可以在CLR存储过程中访问所需的Web方法。

WSDL.exe实用程序可以在已安装的Microsoft SDK中找到,我使用Windows 7版本运行了我的程序,但是您的硬盘驱动器的简单搜索应该为您提供您的位置,该位置安装在以下目录中:C:\程序文件(x86)\微软的SDK \的Windows \ v7.0A \ BIN

的命令运行WSDL.EXE实用程序时使用的是:

WSDL.exe /o:(name of Visual Studio Class file) /n:(name of namespace) (address of webservice) 

例如:

WSDL.exe /o:Weather.cs /n:Weather.Test http://http://wsf.cdyne.com/WeatherWS/Weather.asmx 

这将在此实例中生成一个Weather.cs文件,然后您可以将其添加到您的项目并在您的方法中调用。

+0

声音有趣,你能告诉我在哪里可以找到WSDL实用程序吗?这是在VS或微软的SQL服务器管理工​​作室的东西? – ErikL 2014-10-07 12:01:34

+0

@ErikL我昨天有一天学习如何成为一名咖啡师(只是incase :))我已经更新了我的答案,以显示你将如何打电话给wsdl.exe – Mattgb 2014-10-08 08:16:16

2

制造这个庞然大物对于我自己的需要

CREATE PROCEDURE [dbo].[RequestHttpWebService] 
@Url varchar(1024), 
@HttpMethod varchar(10), 
@ParamsValues varchar(1024), -- param1=value&param2=value 
@SoapAction varchar(1024) = null 

AS BEGIN SET NOCOUNT ON;

--set @Url = 'http://localhost/service.asmx' 
--set @HttpMethod = 'soap' 
--set @ParamsValues = 'login=tr2280&password=Qwe12345&domain=webtech.development' 
--set @SoapAction = 'Authenticate' 


if @HttpMethod in ('get','GET') and len(@ParamsValues) > 0 
begin 
    set @Url = @Url + '?' + @ParamsValues 
end 

declare @obj int 
    ,@response varchar(8000) 
    ,@responseXml xml 
    ,@status varchar(50) 
    ,@statusText varchar(1024) 
    ,@method varchar(10) = (case when @HttpMethod in ('soap','SOAP') then 'POST' else @HttpMethod end) 

exec sp_OACreate 'MSXML2.ServerXMLHttp', @obj out 
exec sp_OAMethod @obj, 'Open', null, @method, @Url, false 

if @HttpMethod in ('get','GET') 
begin 
    exec sp_OAMethod @obj, 'send' 
end 
else if @HttpMethod in ('post','POST') 
begin 
    exec sp_OAMethod @obj, 'setRequestHeader', null, 'Content-Type', 'application/x-www-form-urlencoded' 
    exec sp_OAMethod @obj, 'send', null, @ParamsValues 
end 
else if @HttpMethod in ('soap','SOAP') 
begin 
    if @SoapAction is null 
     raiserror('@SoapAction is null', 10, 1) 

    declare @host varchar(1024) = @Url 
    if @host like 'http://%' 
     set @host = right(@host, len(@host) - 7) 
    else if @host like 'https://%' 
     set @host = right(@host, len(@host) - 8) 

    if charindex(':', @host) > 0 and charindex(':', @host) < charindex('/', @host) 
     set @host = left(@host, charindex(':', @host) - 1) 
    else 
     set @host = left(@host, charindex('/', @host) - 1) 

    declare @envelope varchar(8000) = '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><{action} xmlns="http://tempuri.org/">{params}</{action}></soap:Body></soap:Envelope>' 
    declare @params varchar(8000) = '' 

    WHILE LEN(@ParamsValues) > 0 
    BEGIN 
     declare @param varchar(256), 
       @value varchar(256) 

     IF charindex('&', @ParamsValues) > 0 
     BEGIN 

      SET @param = left(@ParamsValues, charindex('&', @ParamsValues) - 1) 
      set @value = RIGHT(@param, len(@param) - charindex('=', @param)) 
      set @param = left(@param, charindex('=', @param) - 1) 
      set @params = @params + '<' + @param + '>' + @value + '</'+ @param + '>' 
      SET @ParamsValues = right(@ParamsValues, LEN(@ParamsValues) - LEN(@param + '=' + @value + '&')) 
     END 
     ELSE 
     BEGIN 
      set @value = RIGHT(@ParamsValues, len(@ParamsValues) - charindex('=', @ParamsValues)) 
      set @param = left(@ParamsValues, charindex('=', @ParamsValues) - 1) 

      set @params = @params + '<' + @param + '>' + @value + '</'+ @param + '>' 
      SET @ParamsValues = NULL 
     END 
    END 

    set @envelope = replace(@envelope, '{action}', @SoapAction) 
    set @envelope = replace(@envelope, '{params}', @params) 

    set @SoapAction = 'http://tempuri.org/' + @SoapAction 

    print @host 
    print @SoapAction 
    print @envelope 

    exec sp_OAMethod @obj, 'setRequestHeader', null, 'Content-Type', 'text/xml; charset=utf-8' 
    exec sp_OAMethod @obj, 'setRequestHeader', null, 'Host', @host 
    exec sp_OAMethod @obj, 'setRequestHeader', null, 'SOAPAction', @SoapAction 
    exec sp_OAMethod @obj, 'send', null, @envelope 
end 

exec sp_OAGetProperty @obj, 'responseText', @response out 
exec sp_OADestroy @obj 

select @status as [status], @statusText as [statusText], @response as [response] 

END

GO

+0

非常感谢你...这使我的工作如此简单 – 2017-07-13 14:03:15