TSQLでWebサービスを呼び出すストアドプロシージャを構築しようとしています。これは以前にOracleで行ったことがありますが、MSSQLではそれほど簡単ではないようです。もちろん、ストアドプロシージャでこれを行わない理由はたくさんありますが、このプロシージャは毎日のバッチでのみ使用されるため、パフォーマンスはそれほど問題になりません。私がやりたいことは次のとおりです:フルネームをWebサービスに送信すると、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サーバーデータベースプロジェクト」を作成した後、ソリューションのコンテキストメニューで[Web参照の追加]を選択できません、メニューにはnuのようなオプションがあります。
過去に私は次の方法を使用しましたが、最近は最善の方法ではないかもしれませんが、私にとってはうまくいきました:
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サービスを呼び出しました。
私自身のニーズのためにこのモンスターを作りました
CREATE PROCEDURE [dbo].[RequestHttpWebService]
@Url varchar(1024),
@HttpMethod varchar(10),
@ParamsValues varchar(1024), -- param1=value¶m2=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
編集:書式設定
私もこの問題に遭遇しました。 T-SQLのパラメーターを使用してHTTP Postを実行する適切な方法は次のとおりです。
DECLARE @authHeader NVARCHAR(64);
DECLARE @contentType NVARCHAR(64);
DECLARE @postData NVARCHAR(2000);
DECLARE @responseText NVARCHAR(2000);
DECLARE @responseXML NVARCHAR(2000);
DECLARE @ret INT;
DECLARE @status NVARCHAR(32);
DECLARE @statusText NVARCHAR(32);
DECLARE @token INT;
DECLARE @url NVARCHAR(256);
SET @authHeader = 'BASIC 0123456789ABCDEF0123456789ABCDEF';
SET @contentType = 'application/x-www-form-urlencoded';
SET @postData = 'value1=Hello&value2=World'
SET @url = 'https://requestb.in/16xdq1p1'
-- Open the connection.
EXEC @ret = sp_OACreate 'MSXML2.ServerXMLHTTP', @token OUT;
IF @ret <> 0 RAISERROR('Unable to open HTTP connection.', 10, 1);
-- Send the request.
EXEC @ret = sp_OAMethod @token, 'open', NULL, 'POST', @url, 'false';
EXEC @ret = sp_OAMethod @token, 'setRequestHeader', NULL, 'Authentication', @authHeader;
EXEC @ret = sp_OAMethod @token, 'setRequestHeader', NULL, 'Content-type', @contentType;
EXEC @ret = sp_OAMethod @token, 'send', NULL, @postData;
-- Handle the response.
EXEC @ret = sp_OAGetProperty @token, 'status', @status OUT;
EXEC @ret = sp_OAGetProperty @token, 'statusText', @statusText OUT;
EXEC @ret = sp_OAGetProperty @token, 'responseText', @responseText OUT;
-- Show the response.
PRINT 'Status: ' + @status + ' (' + @statusText + ')';
PRINT 'Response text: ' + @responseText;
-- Close the connection.
EXEC @ret = sp_OADestroy @token;
IF @ret <> 0 RAISERROR('Unable to close HTTP connection.', 10, 1);
編集:ここで呼び出していたサンプルサービスがシャットダウンしたようです。 URLが機能することを確認するには、URLを交換して別のエンドポイントに投稿する必要があります。
Visual StudioでSQL Serverプロジェクトを維持する場合、通常の方法でWeb参照を追加することはできません。ただし、WSDLユーティリティを使用してWebインターフェイスを作成し、これをソリューションに追加できます。その後、CLRストアドプロシージャで必要なWebメソッドにアクセスできるようになります。
WSDL.exeユーティリティは、インストールされたMicrosoft SDK内にあります。私はWindows 7バージョンを使用して実行しましたが、HDDを単純に検索すると、次のディレクトリにインストールされた場所がわかります:C:\Program Files (x86)\Microsoft SDKs\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://wsf.cdyne.com/WeatherWS/Weather.asmx
これにより、このインスタンスでWeather.cs
ファイルが生成され、プロジェクトに追加して、メソッド内で呼び出すことができます。