Related
I try to create a new procedure to getting real currency exchange rates from website. To do this one, i use OLE Automation Stored Procedures. But i have encountered a problem when i trying to get data with sp_OAGetProperty from XML.
When i try to inserted a XML into a temporary table with sp_OASetProperty, it gives me an error. I tried many things to fix that but that solutions mostly about XML and i don't know about XML very much. Here is the problematic part of my code:
DECLARE #OBJ AS INT
DECLARE #RESULT AS INT
EXEC #RESULT=sp_OACreate 'MSXML2.XMLHTTP', #OBJ OUT
EXEC #RESULT=sp_OAMethod #OBJ , 'open' , null , 'GET', #url, false
EXEC #RESULT=sp_OAMethod #OBJ, SEND, NULL,''
IF OBJECT_ID('tempdb..#XML') IS NOT Null DROP TABLE #XML
CREATE TABLE #XML (STRXML VARCHAR(max))
INSERT INTO #XML (STRXML) EXEC #RESULT = sp_OASetProperty #OBJ,'responseXML.xml' ---> I am getting an error in this stage.
SELECT * FROM #XML
I expect the xml like this:
<?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="isokur.xsl"?> <Tarih_Date Tarih="18.09.2019" Date="09/18/2019" Bulten_No="2019/175"> ....... </Tarih_Date>
But the output is an empty result. When i exec sp_OAGetErrorInfo to get error it shows that error:
Error Code: 0x80042727
Description: sp_OASetProperty usage: ObjPointer int IN, PropertyName varchar IN, #setval <any> IN [, additional indexing IN params].
I would advise you to use an SQL CLR stored procedure to make web service calls and avoid MSXML2.XMLHTTP. MSXML2.XMLHTTP in particular, and OLE objects in general, are not thread safe meaning that concurrent calls from SQL may cause problems.
The following, based on Call a webservice from TSQL (Stored Procedure) using MSXML, does work on SQL Server 2017 (64-bit)...
/*
exec sp_configure 'Ole Automation Procedures', 1
go
reconfigure
go
*/
declare #TableVariable table (result nvarchar(max));
declare #hResult int, #object int, #Status nvarchar(max), #StatusText nvarchar(max), #Response nvarchar(max)
declare #url nvarchar(max) = 'http://www.geoplugin.net/xml.gp?ip=8.8.8.8'
declare #FailPoint nvarchar(max) = 'Create'
exec #hResult = sp_OACreate 'MSXML2.XMLHTTP', #object out
if (#hResult = 0)
begin
set #FailPoint = 'Open'
exec #hResult = sp_OAMethod #object , 'Open', null, 'GET', #url, 0
end
if (#hResult = 0)
begin
set #FailPoint = 'Send'
exec #hResult = sp_OAMethod #object, 'Send'
end
if (#hResult = 0)
begin
set #FailPoint = 'Status'
delete #TableVariable
insert #TableVariable exec #hResult = sp_OAMethod #object, 'Status'
select #Status=result from #TableVariable;
end
if (#hResult = 0)
begin
set #FailPoint = 'StatusText'
delete #TableVariable
insert #TableVariable exec #hResult = sp_OAMethod #object, 'StatusText'
select #StatusText=result from #TableVariable
end
if (#hResult = 0)
begin
set #FailPoint = 'ResponseText'
delete #TableVariable
insert #TableVariable exec #hResult = sp_OAMethod #object, 'ResponseText'
select #Response=result from #TableVariable
end
if (#hResult != 0)
begin
declare #Source nvarchar(max), #Description nvarchar(max)
exec sp_OAGetErrorInfo #object, #Source out, #Description out
select
hResult = convert(varbinary(4), #hResult),
Source = #Source,
Description = #Description,
FailPoint = #FailPoint
goto Destroy
end
select [Status]=#Status, [StatusText]=#StatusText, [Response]=#Response
Destroy:
exec #hResult = sp_OADestroy #object
go
If you're confident that the response is valid XML then you can follow up with cast(#Response as xml).
I wanted to send an HTTP request from SQL server to Tomcat server. I have installed SQL server 2012 express and non .NET application in Tomcat server. I have gone through this like Make a HTTP request from SQL server
As it says in the above article, "The COM object WinHttp.WinHttpRequest.5.1 must be installed on the server, some typical variations are WinHttp.WinHttpRequest.5".
I have downloaded winhttp.zip from the winhttp download link, found winhttp.dll in the zip folder and pasted it in C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER2\MSSQL\Binn as suggested in this msdn link.
Following that same advice, I have executed following line in SSMS:
sp_addextendedproc 'GetHttp',
'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER2\MSSQL\Binn\winhttp.dll';
I also executed the following code in SSMS as said in "Make an HTTP request from SQL server link":
Alter function GetHttp
(
#url varchar(8000)
)
returns varchar(8000)
as
BEGIN
DECLARE #win int
DECLARE #hr int
DECLARE #text varchar(8000)
EXEC #hr=sp_OACreate 'WinHttp.WinHttpRequest.5.1',#win OUT
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
EXEC #hr=sp_OAMethod #win, 'Open',NULL,'GET',#url,'false'
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
EXEC #hr=sp_OAMethod #win,'Send'
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
EXEC #hr=sp_OAGetProperty #win,'ResponseText',#text OUTPUT
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
EXEC #hr=sp_OADestroy #win
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
RETURN #text
END
Then I get the error
Msg 2010, Level 16, State 1, Procedure GetHttp, Line 2
Cannot perform alter on 'GetHttp' because it is an incompatible object type.
I do not know how to call the function to send the HTTP request. I assume it is something like this GetHttp('http://www.google.co.in/').
What am I missing?
I got another answer as well. I created procedure like follows
CREATE procedure HTTP_Request( #sUrl varchar(200))
As
Declare
#obj int
,#hr int
,#msg varchar(255)
exec #hr = sp_OACreate 'MSXML2.ServerXMLHttp', #obj OUT
if #hr <> 0 begin Raiserror('sp_OACreate MSXML2.ServerXMLHttp.3.0
failed', 16,1) return end
exec #hr = sp_OAMethod #obj, 'open', NULL, 'POST', #sUrl, false
if #hr <>0 begin set #msg = 'sp_OAMethod Open failed' goto eh end
exec #hr = sp_OAMethod #obj, 'setRequestHeader', NULL, 'Content-Type',
'application/x-www-form-urlencoded'
if #hr <>0 begin set #msg = 'sp_OAMethod setRequestHeader failed' goto
eh end
exec #hr = sp_OAMethod #obj, send, NULL, ''
if #hr <>0 begin set #msg = 'sp_OAMethod Send failed' goto eh end
exec #hr = sp_OADestroy #obj
return
eh:
exec #hr = sp_OADestroy #obj
Raiserror(#msg, 16, 1)
return
GO
I called the stored procedure with url
USE [master]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[HTTP_Request]
#sUrl = N'url'
SELECT 'Return Value' = #return_value
GO
Thank you guys to make me work this.
That really helped me #niren.
Thought I'd post my amendment that puts it in scalar function and allows you to get the service response. Only downside is scalar funcs can't raiserrors so there's something to think about catching elsewhere.
CREATE function [dbo].[fn_HttpPOST]
(
#sUrl varchar(8000)
)
returns varchar(8000)
as
BEGIN
DECLARE #obj int
DECLARE #hr int
DECLARE #msg varchar(8000)
exec #hr = sp_OACreate 'MSXML2.ServerXMLHttp', #obj OUT
if #hr <> 0 begin set #Msg = 'sp_OACreate MSXML2.ServerXMLHttp.3.0 failed' return #Msg end
exec #hr = sp_OAMethod #obj, 'open', NULL, 'POST', #sUrl, false
if #hr <>0 begin set #msg = 'sp_OAMethod Open failed' goto eh end
exec #hr = sp_OAMethod #obj, 'setRequestHeader', NULL, 'Content-Type', 'application/x-www-form-urlencoded'
if #hr <>0 begin set #msg = 'sp_OAMethod setRequestHeader failed' goto eh end
exec #hr = sp_OAMethod #obj, send, NULL, ''
if #hr <>0 begin set #msg = 'sp_OAMethod Send failed' goto eh end
EXEC #hr=sp_OAGetProperty #Obj,'ResponseText',#msg OUTPUT
IF #hr <> 0 EXEC sp_OAGetErrorInfo #Obj
exec #hr = sp_OADestroy #obj
RETURN #msg
eh:
exec #hr = sp_OADestroy #obj
return #msg
END
I got answer by powershell. What I did is open powershell in sql server then I did execute following code in powershell.
$http_Request= New-Object system.Net.WebClient;
$Result = $http_Request.downloadString("url")
Made this monster for my own needs
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;
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
The most flexible approach here is to use a CLR User Defined Function, which you could simply define in C# as follows;
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString http(SqlString url)
{
var wc = new WebClient();
var html = wc.DownloadString(url.Value);
return new SqlString (html);
}
Full installation instructions are here - https://github.com/infiniteloopltd/SQLHttp
the correct way is to buil a CLR, which will contain a C# code to send http/s request,
since we want to avoid memory leaks and security issues, which using old way like sp_OACreate can cause.
for example :
var request =
(HttpWebRequest)WebRequest.Create("http://www.example.com. /recepticle.aspx");
var postData = "thing1=hello";
postData += "&amp;amp;amp;thing2=world";
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();`
using sp_OACreate is less secure, while CLR can be signed and check by you.
With these codes you can read Html Code from web pages through Httprequest or run SOAP web services.
Make HTTP request from SQLserver.
Send HTTP request via SQL Server.
Calling a SOAP webservice from SQL Server TSQL stored procedure.
Save Http Response To File.
DROP PROCEDURE IF EXISTS [dbo].[stp_HttpRequest]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--1400/02/16-18:06
--Mahmood Khezrian
--Sp For Get Data (Page Html Or Webservice Result) From Web.
--Can Run Any Method (Get - Post , ....)
--Can Run Soap WebService
CREATE proc [dbo].[stp_HttpRequest]
#URI varchar(max) = N''
,#MethodName [sysname] = N'Post'
,#RequestBody nvarchar(max) = N'' --Neded For Run Soap Webservices , Soap XML Data Parameters
,#SoapAction varchar(500) --Neded For Run Soap Webservices
,#UserName [sysname] --(Optonal) Domain\UserName or UserName
,#Password [sysname] --(Optonal)
,#ResponseText nvarchar(max) output --Return Responce Data With This Variable
,#ExportToFile nvarchar(max)=Null --If Pass This Parameter , After Run Request Save Responce Data (Returned Value) To File.
/*With ENCRYPTION*/ As
Set NoCount ON;
Declare #ErrorCode int
Set #ErrorCode = -1
/*Begin Transaction stp_HttpRequest*/
Begin Try
if (#MethodName = '')
RaisError (N'Method Name must be set.',16,1);
if (Patindex(N'%{RandomFileName}%',#ExportToFile)>0) Begin
Declare #FileName [sysname]
Set #FileName = Format(GetDate(),N'yyyyMMddHHmmss')+N'_'+Replace(NewID(),'-','')
Set #ExportToFile = Replace(#ExportToFile,N'{RandomFileName}',#FileName)
End--if
Set #RequestBody = REPLACE(#RequestBody,'&','&')
Set #ResponseText = N'FAILED'
Declare #objXmlHttp int
Declare #hResult int
Declare #source varchar(255), #desc varchar(255)
Set #ErrorCode = -100
Exec #hResult = sp_OACreate N'MSXML2.ServerXMLHTTP', #objXmlHttp OUT
IF (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'Create failed MSXML2.ServerXMLHTTP',
MedthodName = #MethodName
RaisError (N'Create failed MSXML2.ServerXMLHTTP.',16,1);
End--if
Set #ErrorCode = -2
-- open the destination URI with Specified method
Exec #hResult = sp_OAMethod #objXmlHttp, N'open', Null, #MethodName, #URI, N'false', #UserName, #Password
if (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'Open failed',
MedthodName = #MethodName
RaisError (N'Open failed.',16,1);
End--if
Set #ErrorCode = -300
-- Set Timeout
--Exec #hResult = sp_OAMethod #objXmlHttp, N'setTimeouts', Null, 5000,5000,15000,30000
Exec #hResult = sp_OAMethod #objXmlHttp, N'setTimeouts', Null, 10000,10000,30000,60000
if (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'SetTimeouts failed',
MedthodName = #MethodName
RaisError (N'SetTimeouts failed.',16,1);
End--if
Set #ErrorCode = -400
-- set request headers
Exec #hResult = sp_OAMethod #objXmlHttp, N'setRequestHeader', Null, N'Content-Type', 'text/xml;charset=UTF-8'
if (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'SetRequestHeader failed',
MedthodName = #MethodName
RaisError (N'SetRequestHeader (Content-Type) failed.',16,1);
End--if
Set #ErrorCode = -500
-- set soap action
if (IsNull(#SoapAction,'')!='') Begin
Exec #hResult = sp_OAMethod #objXmlHttp, N'setRequestHeader', Null, N'SOAPAction', #SoapAction
IF (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'SetRequestHeader (SOAPAction) failed',
MedthodName = #MethodName
RaisError (N'SetRequestHeader failed.',16,1);
End--if
End--if
Set #ErrorCode = -600
--Content-Length
Declare #len int
set #len = len(#RequestBody)
Exec #hResult = sp_OAMethod #objXmlHttp, N'setRequestHeader', Null, N'Content-Length', #len
IF (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'SetRequestHeader (Content-Length) failed',
MedthodName = #MethodName
RaisError (N'SetRequestHeader failed.',16,1);
End--if
-- if you have headers in a Table called RequestHeader you can go through them with this
/*
Set #ErrorCode = -700
Declare #HeaderKey varchar(500), #HeaderValue varchar(500)
Declare RequestHeader CURSOR
LOCAL FAST_FORWARD
FOR
Select HeaderKey, HeaderValue
FROM RequestHeaders
WHERE Method = #MethodName
OPEN RequestHeader
FETCH NEXT FROM RequestHeader
INTO #HeaderKey, #HeaderValue
WHILE ##FETCH_STATUS = 0
BEGIN
Set #ErrorCode = -800
--Select #HeaderKey, #HeaderValue, #MethodName
Exec #hResult = sp_OAMethod #objXmlHttp, 'setRequestHeader', Null, #HeaderKey, #HeaderValue
IF #hResult <> 0
BEGIN
Set #ErrorCode = -900
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = 'SetRequestHeader failed',
MedthodName = #MethodName
RaisError (N'SetRequestHeader failed.',16,1);
END
FETCH NEXT FROM RequestHeader
INTO #HeaderKey, #HeaderValue
END
CLOSE RequestHeader
DEALLOCATE RequestHeader
*/
Set #ErrorCode = -1000
-- send the request
Exec #hResult = sp_OAMethod #objXmlHttp, N'send', Null, #RequestBody
IF (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'Send failed',
MedthodName = #MethodName
RaisError (N'Send failed.',16,1);
End--if
Declare #StatusText varchar(1000), #Status varchar(1000)
Set #ErrorCode = -1100
-- Get status text
Exec sp_OAGetProperty #objXmlHttp, N'StatusText', #StatusText out
Exec sp_OAGetProperty #objXmlHttp, N'Status', #Status out
Select #Status As Status, #StatusText As statusText, #MethodName As MethodName
-- Get response text
Declare #Json Table (Result ntext)
Declare #Xml xml
Set #ErrorCode = -1200
Insert #Json(Result)
Exec #hResult = dbo.sp_OAGetProperty #objXmlHttp, N'ResponseText'
Set #ErrorCode = -1300
--Exec #hResult = dbo.sp_OAGetProperty #objXmlHttp, N'ResponseText', #ResponseText out
IF (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'ResponseText failed',
MedthodName = #MethodName
RaisError (N'ResponseText failed.',16,1);
END--if
Set #ErrorCode = -1400
--Set #ResponseText=Replicate(Convert(varchar(max),N'1'),1000000)
if (IsNull(#SoapAction,'')!='') Begin
Select #Xml=CAST(Replace(Replace(Replace(Cast(Result As nvarchar(max)),N'utf-8',N'utf-16'),N'.0,',N','),N'.00,',N',') As XML)
From #Json
Set #ErrorCode = -1500
Select #ResponseText = x.Rec.query(N'./*').value('.',N'nvarchar(max)')
From #Xml.nodes(N'.') as x(Rec)
End--if
Else Begin
Select #ResponseText= Result From #Json
End--Else
Set #ErrorCode = -1600
--Export To File
if (IsNull(#ExportToFile,'')!='') Begin
Declare #objToFile int
Declare #FileID int
Set #ErrorCode = -1700
--Create Object
Exec #hResult = sp_OACreate 'Scripting.FileSystemObject', #objToFile OUT
IF (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'Create failed Scripting.FileSystemObject',
MedthodName = #MethodName
RaisError (N'Create failed Scripting.FileSystemObject.',16,1);
End--if
Set #ErrorCode = -1800
--Create Or Open File
Exec #hResult = sp_OAMethod #objToFile, 'OpenTextFile' , #FileID OUT, #ExportToFile,2,1,-1
if (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'OpenTextFile failed',
MedthodName = #MethodName
RaisError (N'OpenTextFile failed.',16,1);
End--if
Set #ErrorCode = -1900
--Write Data To File
Exec #hResult = sp_OAMethod #FileID, 'Write', Null, #ResponseText
if (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'Write To File failed',
MedthodName = #MethodName
RaisError (N'Write To File failed.',16,1);
End--if
Set #ErrorCode = -2000
--Close File
Exec sp_OAMethod #FileID, 'Close'
--Delete Objects
Exec sp_OADestroy #FileID
Exec sp_OADestroy #objToFile
End--if
Set #ErrorCode = 0
/*If (##TranCount > 0)
Commit Transaction stp_HttpRequest*/
End Try
Begin Catch
/*If (##TranCount > 0)
Rollback Transaction stp_HttpRequest*/
Exec [dbo].[stp_GetErrorInfo]
End Catch
Exec sp_OADestroy #objXmlHttp
Return #ErrorCode
GO
--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//
--Example For Run Soap WebService
DECLARE #RC int
DECLARE #URI varchar(max)
DECLARE #MethodName sysname
DECLARE #RequestBody nvarchar(max)
DECLARE #SoapAction varchar(500)
DECLARE #UserName sysname=''
DECLARE #Password sysname=''
DECLARE #ResponseText nvarchar(max)
DECLARE #intA nvarchar(10)
DECLARE #intB nvarchar(10)
Set #intA = N'100'
Set #intB = N'200'
Set #URI = N'http://www.dneonline.com/calculator.asmx'
Set #MethodName = N'POST'
Set #RequestBody =
N'<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>
<Add xmlns="http://tempuri.org/"><intA>'+#intA+'</intA><intB>'+#intB+'</intB></Add>
</soap:Body>
</soap:Envelope>'
Set #SoapAction = N'http://tempuri.org/Add'
EXECUTE #RC = [dbo].[stp_HttpRequest]
#URI
,#MethodName
,#RequestBody
,#SoapAction
,#UserName
,#Password
,#ResponseText OUTPUT
Print #ResponseText
Print Len(#ResponseText)
Go
--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//
--Example For Feach Data From Website
DECLARE #RC int
DECLARE #URI varchar(max)
DECLARE #MethodName sysname
DECLARE #RequestBody nvarchar(max)
DECLARE #SoapAction varchar(500)
DECLARE #UserName sysname
DECLARE #Password sysname
DECLARE #ResponseText nvarchar(max)
Declare #ExportToFile nvarchar(max)
Set #URI = N'https://stackoverflow.com/questions/17407338/how-can-i-make-http-request-from-sql-server'
Set #MethodName = N'GET'
Set #RequestBody = N''
Set #SoapAction = N''
Set #ExportToFile = N'C:\Temp\Export\{RandomFileName}.html'
EXECUTE #RC = [dbo].[stp_HttpRequest]
#URI
,#MethodName
,#RequestBody
,#SoapAction
,#UserName
,#Password
,#ResponseText OUTPUT
,#ExportToFile
Print #ResponseText
Print Len(#ResponseText)
Go
Declare #Object as Int;
Declare #ResponseText as Varchar(8000);
Declare #Url as Varchar(MAX);
set #Url = 'http://mysite.ru/cgi-bin/my_xml.cgi'
Exec sp_OACreate 'MSXML2.XMLHTTP', #Object OUT;
Exec sp_OAMethod #Object, 'open', NULL, 'get', #Url, 'false'
Exec sp_OAMethod #Object, 'send'
Exec sp_OAMethod #Object, 'responseText', #ResponseText OUTPUT
Exec sp_OADestroy #Object
SELECT #ResponseText
XML length in url is 4210 and #ResponseText return NULL , when I change length to 3970 #ResponseText return me data. Does sp_OACreate have limit 400 ? If yes if it possible to avoid ?
despite the subject of your post i think that the issue is likely with sp_OAMethod and not sp_OACreate itself.
also IMHO accessing the web from sql code should be avoided at all costs but this is just my opinion because i don't like the idea having a RDBMS 'surfing the web'. ^^
to circumvent the limitation of sp_OAMethod you can try to elaborate an answer present on msdn.
your code should become something like this:
Declare #Object as Int;
Declare #ResponseText as Varchar(8000);
Declare #Url as Varchar(MAX);
set #Url = 'http://mysite.ru/cgi-bin/my_xml.cgi'
Exec sp_OACreate 'MSXML2.XMLHTTP', #Object OUT;
Exec sp_OAMethod #Object, 'open', NULL, 'get', #Url, 'false'
Exec sp_OAMethod #Object, 'send'
--Exec sp_OAMethod #Object, 'responseText', #ResponseText OUTPUT
INSERT #temptable ( appropriatefield )
EXEC #Result = sp_OAGetProperty #Obj, 'YourPropertyName'
Exec sp_OADestroy #Object
the solution requires a temp table with appropriate structure and datatype to store the value produced by the remote page and this should allow you to get more than 4k of data.
According to this thread on sqlservercentral.com, sp_OACreate is limited to 4000 characters.
A workaround is to split up the read into smaller "chunks" that are then concated together in SQL. Here is a code snippet from the above link, that might help you although it reads XML from file instead of through HTTP:
EXECUTE #hResult = sp_OACreate ''Scripting.FileSystemObject'' , #objFileSystem OUT
IF #hResult <> 0
BEGIN
EXEC sp_OAGetErrorInfo #objFileSystem, #ErrorSource OUT, #ErrorDesc OUT
SET #ErrorFailPoint = ''Creating FSO''
GOTO DestroyFSO
RETURN
END
SET #FileNameAndPath = #Path + ''\'' + #FileName
-- Read file
EXECUTE #hResult = sp_OAMethod #objFileSystem, ''OpenTextFile'', #objTextStream OUT, #FileNameAndPath, 1, false, 0--for reading, FormatASCII
IF #hResult <> 0
BEGIN
EXEC sp_OAGetErrorInfo #objFileSystem, #ErrorSource OUT, #ErrorDesc OUT
SET #ErrorFailPoint = ''Opening Reponse File''
GOTO Destroy
RETURN
END
SET #ResponseText = ''''
WHILE #hResult = 0
BEGIN
EXECUTE #hResult = sp_OAGetProperty #objTextStream, ''AtEndOfStream'', #YesOrNo OUTPUT
IF #hResult <> 0
BEGIN
EXEC sp_OAGetErrorInfo #objTextStream, #ErrorSource OUT, #ErrorDesc OUT
SET #ErrorFailPoint = ''Checking AtEndOfStream''
GOTO Destroy
RETURN
END
IF #YesOrNo <> 0
BREAK
EXECUTE #hResult = sp_OAMethod #objTextStream, ''Read'', #Chunk OUTPUT, 4000
IF #hResult <> 0
BEGIN
EXEC sp_OAGetErrorInfo #objTextStream, #ErrorSource OUT, #ErrorDesc OUT
SET #ErrorFailPoint = ''Reading Chunk''
GOTO Destroy
RETURN
END
SET #ResponseText = #ResponseText + ISNULL(#Chunk, '''')
END
EXECUTE #hResult = sp_OAMethod #objTextStream, ''Close''
IF #hResult <> 0
BEGIN
EXEC sp_OAGetErrorInfo #objTextStream, #ErrorSource OUT, #ErrorDesc OUT
SET #ErrorFailPoint = ''Closing Response File''
GOTO Destroy
RETURN
END
-- Record response info
SET #ResponseXml = CAST(#ResponseText AS XML)
Destroy:
EXEC sp_OADestroy #objTextStream
DestroyFSO:
EXEC sp_OADestroy #objFileSystem
This is what I use to overcome the limitation. I use it for a RESTful api communication. I can receive varchar(max) but am still limited on the amount of data I can send. This might get you where you need to be. The top 5 variables are the arguments I use for the sproc.
Declare #url as varchar(1024)
Declare #connection_type as varchar(6)='GET' --POST, PUT, GET DELETE
Declare #post_string as varchar(max)=null
Declare #response_text as Varchar(max)
Declare #content_type varchar(254)='application/json'
Declare #oa_object as Int;
Declare #err_code as Int
Declare #result_table Table (xml_result varchar(max))
Select #post_string=dbo.fn_regex_replace('([ ]{2,10})|\r|\n', #post_string,'') --remove carriage returns and multiple spaces
Exec #err_code=sp_OACreate 'MSXML2.ServerXMLHTTP.3.0', #oa_object OUT;
If #err_code<>0
Set #response_text=dbo.fn_oa_error_message(#oa_object)
Else
Begin
Exec #err_code=sp_OAMethod #oa_object, 'open', NULL, #connection_type, #url,'false','d0b1a0aaed2a529356471de4fe99cae2','8e7aa1a91fa68d06cd027914d3aa1140'
If #err_code<>0
Set #response_text='Open '+dbo.fn_oa_error_message(#oa_object)
Else
Begin
Exec #err_code=sp_OAMethod #oa_object, 'setRequestHeader', NULL, 'User-Agent', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)'
If #err_code<>0
Set #response_text='setRequestHeader:User-Agent '+dbo.fn_oa_error_message(#oa_object)
Else
Begin
Exec #err_code=sp_OAMethod #oa_object, 'setRequestHeader', NULL, 'Content-Type', #content_type
If #err_code<>0
Set #response_text='setRequestHeader:Content-Type '+dbo.fn_oa_error_message(#oa_object)
Else
Begin
Exec #err_code=sp_OAMethod #oa_object, 'send', Null, #post_string
If #err_code<>0
Set #response_text='Send '+dbo.fn_oa_error_message(#oa_object)
Else
Begin
Set #response_text=null--make sure we don't return garbage
INSERT #result_table (xml_result)
Exec #err_code = sp_OAGetProperty #oa_object, 'responseText'
If #err_code<>0
Set #response_text='responseText '+dbo.fn_oa_error_message(#oa_object)
Else
SELECT #response_text=xml_result FROM #result_table
End
End
End
End
End
Exec sp_OADestroy #oa_object
Although you don't need it, the error handler is below. It helps with troubleshooting.
CREATE FUNCTION
dbo.n_oa_error_message(#oa_object int)
RETURNS varchar(max)
AS
BEGIN
Declare #source varchar(255)
Declare #description varchar(255)
exec sp_OAGetErrorInfo #oa_object, #source OUT, #description OUT
return 'Error: '+IsNull(#description,'no description')
END
I used the following query to solve this issue. The problem is probably not sp_OACreate or sp_OAMethod, but the way to return the #ResponseText. Inserting the data into a table variable instead of using "#ResponseText OUTPUT" is the key. Note that I changed the #Response to VARCHAR(MAX).
DECLARE #TABLEVAR TABLE (responseXml VARCHAR(MAX))
DECLARE #URL VARCHAR(200)
SELECT #URL = 'http://mysite/php-start/callxml.php'
DECLARE #Response NVARCHAR(MAX)
DECLARE #Xml XML
DECLARE #Obj INT
DECLARE #Result INT
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, ''
INSERT INTO #TABLEVAR
EXEC #Result = sp_OAGetProperty #Obj, 'responseXML.xml'--, #Response OUT
EXEC sp_OADestroy #Obj
SELECT #Response = responseXml FROM #TABLEVAR
SELECT #Xml = CONVERT(XML, #Response, 2)
DECLARE #handle INT
EXEC sp_xml_preparedocument #handle OUTPUT, #Xml
SELECT *
FROM OPENXML(#handle, '/data/record', 2)
WITH [dbo].[tblDialogTechTemp]
EXEC sp_xml_removedocument #handle
My query suddenly returned null without changing anything. After changing 'MSXML2.XMLHttp' to 'MSXML2.ServerXMLHTTP', it started to work again. To know more about the difference between these two, see this article and Microsoft documentation.
I am trying to build a stored procedure in TSQL to call a webservice. I've done this before in Oracle, but it seems like it's not so easy in MSSQL.
There are of course many reasons not to do this in a stored proc, but since this procedure is only to be used in a daily batch, performance is not too much of a issue.
The thing I want to do is as follows: Send a full name to the webservice, the webservice will return a name divided in things like first name, prefix, lastname, etc. The returned values will need to be written to a table.
I found a interesting procedure at http://www.vishalseth.com/post/2009/12/22/Call-a-webservice-from-TSQL-(Stored-Procedure)-using-MSXML.aspx wich seemed to do exactly what I want, but as soon as you add a body to the call, I run into errors like "The parameter is incorrect". This is also stated in the article, and apparently there's no easy solution for it. I definitely need to send a request body.
I also read lots of articles about solving it with CLI or the "Web Service Task Editor", or "SSIS" bit I couldn't find any tutorials about where to start. Right now I only have Microsoft SQL server management studio.
I'm on SQL server 2012 by the way.
Any ideas about what direction I should go with this?
I've already found this description, wich seems pretty clean: http://www.databasejournal.com/features/mssql/article.php/3821271/Calling-a-Web-Service-from-within-SQL-Server.htm However, after installing visual studio 2012 and creating a "SQL server database project", I am unable to choose "Add Web Reference" in the solution context menu, there's just nu such option in the menu.
In the past I have used the following method, it may not be the best method these days but it has worked successfully for me :
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
I have used this to call a webservice which produces a report and emails it within the method.
Made this monster for my own needs
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
edit: formatting
I ran into this issue as well. Here is the proper way to execute an HTTP Post with parameters from T-SQL:
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);
Credit goes to the original author.
Edit: The example service I was calling here appears to have shut down. You will need to swap out the URL and post to a different endpoint in order to see it working.
You cannot add a Web Reference in the usual way when maintaining a SQL Server Project in Visual Studio. However, you can use the WSDL Utility to create the Web Interface and add this to your solution. Subsequently, you will then be able to access the Web Methods that you want in your CLR Stored Procedure.
The WSDL.exe utility can be found within the installed Microsoft SDK's, I ran mine using the Windows 7 version but a simple search of your HDD should give you your location, which was installed in the following directory: C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin
The commands to use when running the WSDL.exe utility are:
WSDL.exe /o:(name of Visual Studio Class file) /n:(name of namespace) (address of webservice)
for example:
WSDL.exe /o:Weather.cs /n:Weather.Test http://wsf.cdyne.com/WeatherWS/Weather.asmx
This will generate a Weather.cs file in this instance which you can then add to your project and call within your method.
I wanted to send an HTTP request from SQL server to Tomcat server. I have installed SQL server 2012 express and non .NET application in Tomcat server. I have gone through this like Make a HTTP request from SQL server
As it says in the above article, "The COM object WinHttp.WinHttpRequest.5.1 must be installed on the server, some typical variations are WinHttp.WinHttpRequest.5".
I have downloaded winhttp.zip from the winhttp download link, found winhttp.dll in the zip folder and pasted it in C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER2\MSSQL\Binn as suggested in this msdn link.
Following that same advice, I have executed following line in SSMS:
sp_addextendedproc 'GetHttp',
'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER2\MSSQL\Binn\winhttp.dll';
I also executed the following code in SSMS as said in "Make an HTTP request from SQL server link":
Alter function GetHttp
(
#url varchar(8000)
)
returns varchar(8000)
as
BEGIN
DECLARE #win int
DECLARE #hr int
DECLARE #text varchar(8000)
EXEC #hr=sp_OACreate 'WinHttp.WinHttpRequest.5.1',#win OUT
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
EXEC #hr=sp_OAMethod #win, 'Open',NULL,'GET',#url,'false'
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
EXEC #hr=sp_OAMethod #win,'Send'
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
EXEC #hr=sp_OAGetProperty #win,'ResponseText',#text OUTPUT
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
EXEC #hr=sp_OADestroy #win
IF #hr <> 0 EXEC sp_OAGetErrorInfo #win
RETURN #text
END
Then I get the error
Msg 2010, Level 16, State 1, Procedure GetHttp, Line 2
Cannot perform alter on 'GetHttp' because it is an incompatible object type.
I do not know how to call the function to send the HTTP request. I assume it is something like this GetHttp('http://www.google.co.in/').
What am I missing?
I got another answer as well. I created procedure like follows
CREATE procedure HTTP_Request( #sUrl varchar(200))
As
Declare
#obj int
,#hr int
,#msg varchar(255)
exec #hr = sp_OACreate 'MSXML2.ServerXMLHttp', #obj OUT
if #hr <> 0 begin Raiserror('sp_OACreate MSXML2.ServerXMLHttp.3.0
failed', 16,1) return end
exec #hr = sp_OAMethod #obj, 'open', NULL, 'POST', #sUrl, false
if #hr <>0 begin set #msg = 'sp_OAMethod Open failed' goto eh end
exec #hr = sp_OAMethod #obj, 'setRequestHeader', NULL, 'Content-Type',
'application/x-www-form-urlencoded'
if #hr <>0 begin set #msg = 'sp_OAMethod setRequestHeader failed' goto
eh end
exec #hr = sp_OAMethod #obj, send, NULL, ''
if #hr <>0 begin set #msg = 'sp_OAMethod Send failed' goto eh end
exec #hr = sp_OADestroy #obj
return
eh:
exec #hr = sp_OADestroy #obj
Raiserror(#msg, 16, 1)
return
GO
I called the stored procedure with url
USE [master]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[HTTP_Request]
#sUrl = N'url'
SELECT 'Return Value' = #return_value
GO
Thank you guys to make me work this.
That really helped me #niren.
Thought I'd post my amendment that puts it in scalar function and allows you to get the service response. Only downside is scalar funcs can't raiserrors so there's something to think about catching elsewhere.
CREATE function [dbo].[fn_HttpPOST]
(
#sUrl varchar(8000)
)
returns varchar(8000)
as
BEGIN
DECLARE #obj int
DECLARE #hr int
DECLARE #msg varchar(8000)
exec #hr = sp_OACreate 'MSXML2.ServerXMLHttp', #obj OUT
if #hr <> 0 begin set #Msg = 'sp_OACreate MSXML2.ServerXMLHttp.3.0 failed' return #Msg end
exec #hr = sp_OAMethod #obj, 'open', NULL, 'POST', #sUrl, false
if #hr <>0 begin set #msg = 'sp_OAMethod Open failed' goto eh end
exec #hr = sp_OAMethod #obj, 'setRequestHeader', NULL, 'Content-Type', 'application/x-www-form-urlencoded'
if #hr <>0 begin set #msg = 'sp_OAMethod setRequestHeader failed' goto eh end
exec #hr = sp_OAMethod #obj, send, NULL, ''
if #hr <>0 begin set #msg = 'sp_OAMethod Send failed' goto eh end
EXEC #hr=sp_OAGetProperty #Obj,'ResponseText',#msg OUTPUT
IF #hr <> 0 EXEC sp_OAGetErrorInfo #Obj
exec #hr = sp_OADestroy #obj
RETURN #msg
eh:
exec #hr = sp_OADestroy #obj
return #msg
END
I got answer by powershell. What I did is open powershell in sql server then I did execute following code in powershell.
$http_Request= New-Object system.Net.WebClient;
$Result = $http_Request.downloadString("url")
Made this monster for my own needs
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;
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
The most flexible approach here is to use a CLR User Defined Function, which you could simply define in C# as follows;
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString http(SqlString url)
{
var wc = new WebClient();
var html = wc.DownloadString(url.Value);
return new SqlString (html);
}
Full installation instructions are here - https://github.com/infiniteloopltd/SQLHttp
the correct way is to buil a CLR, which will contain a C# code to send http/s request,
since we want to avoid memory leaks and security issues, which using old way like sp_OACreate can cause.
for example :
var request =
(HttpWebRequest)WebRequest.Create("http://www.example.com. /recepticle.aspx");
var postData = "thing1=hello";
postData += "&amp;amp;amp;thing2=world";
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();`
using sp_OACreate is less secure, while CLR can be signed and check by you.
With these codes you can read Html Code from web pages through Httprequest or run SOAP web services.
Make HTTP request from SQLserver.
Send HTTP request via SQL Server.
Calling a SOAP webservice from SQL Server TSQL stored procedure.
Save Http Response To File.
DROP PROCEDURE IF EXISTS [dbo].[stp_HttpRequest]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--1400/02/16-18:06
--Mahmood Khezrian
--Sp For Get Data (Page Html Or Webservice Result) From Web.
--Can Run Any Method (Get - Post , ....)
--Can Run Soap WebService
CREATE proc [dbo].[stp_HttpRequest]
#URI varchar(max) = N''
,#MethodName [sysname] = N'Post'
,#RequestBody nvarchar(max) = N'' --Neded For Run Soap Webservices , Soap XML Data Parameters
,#SoapAction varchar(500) --Neded For Run Soap Webservices
,#UserName [sysname] --(Optonal) Domain\UserName or UserName
,#Password [sysname] --(Optonal)
,#ResponseText nvarchar(max) output --Return Responce Data With This Variable
,#ExportToFile nvarchar(max)=Null --If Pass This Parameter , After Run Request Save Responce Data (Returned Value) To File.
/*With ENCRYPTION*/ As
Set NoCount ON;
Declare #ErrorCode int
Set #ErrorCode = -1
/*Begin Transaction stp_HttpRequest*/
Begin Try
if (#MethodName = '')
RaisError (N'Method Name must be set.',16,1);
if (Patindex(N'%{RandomFileName}%',#ExportToFile)>0) Begin
Declare #FileName [sysname]
Set #FileName = Format(GetDate(),N'yyyyMMddHHmmss')+N'_'+Replace(NewID(),'-','')
Set #ExportToFile = Replace(#ExportToFile,N'{RandomFileName}',#FileName)
End--if
Set #RequestBody = REPLACE(#RequestBody,'&','&')
Set #ResponseText = N'FAILED'
Declare #objXmlHttp int
Declare #hResult int
Declare #source varchar(255), #desc varchar(255)
Set #ErrorCode = -100
Exec #hResult = sp_OACreate N'MSXML2.ServerXMLHTTP', #objXmlHttp OUT
IF (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'Create failed MSXML2.ServerXMLHTTP',
MedthodName = #MethodName
RaisError (N'Create failed MSXML2.ServerXMLHTTP.',16,1);
End--if
Set #ErrorCode = -2
-- open the destination URI with Specified method
Exec #hResult = sp_OAMethod #objXmlHttp, N'open', Null, #MethodName, #URI, N'false', #UserName, #Password
if (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'Open failed',
MedthodName = #MethodName
RaisError (N'Open failed.',16,1);
End--if
Set #ErrorCode = -300
-- Set Timeout
--Exec #hResult = sp_OAMethod #objXmlHttp, N'setTimeouts', Null, 5000,5000,15000,30000
Exec #hResult = sp_OAMethod #objXmlHttp, N'setTimeouts', Null, 10000,10000,30000,60000
if (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'SetTimeouts failed',
MedthodName = #MethodName
RaisError (N'SetTimeouts failed.',16,1);
End--if
Set #ErrorCode = -400
-- set request headers
Exec #hResult = sp_OAMethod #objXmlHttp, N'setRequestHeader', Null, N'Content-Type', 'text/xml;charset=UTF-8'
if (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'SetRequestHeader failed',
MedthodName = #MethodName
RaisError (N'SetRequestHeader (Content-Type) failed.',16,1);
End--if
Set #ErrorCode = -500
-- set soap action
if (IsNull(#SoapAction,'')!='') Begin
Exec #hResult = sp_OAMethod #objXmlHttp, N'setRequestHeader', Null, N'SOAPAction', #SoapAction
IF (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'SetRequestHeader (SOAPAction) failed',
MedthodName = #MethodName
RaisError (N'SetRequestHeader failed.',16,1);
End--if
End--if
Set #ErrorCode = -600
--Content-Length
Declare #len int
set #len = len(#RequestBody)
Exec #hResult = sp_OAMethod #objXmlHttp, N'setRequestHeader', Null, N'Content-Length', #len
IF (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'SetRequestHeader (Content-Length) failed',
MedthodName = #MethodName
RaisError (N'SetRequestHeader failed.',16,1);
End--if
-- if you have headers in a Table called RequestHeader you can go through them with this
/*
Set #ErrorCode = -700
Declare #HeaderKey varchar(500), #HeaderValue varchar(500)
Declare RequestHeader CURSOR
LOCAL FAST_FORWARD
FOR
Select HeaderKey, HeaderValue
FROM RequestHeaders
WHERE Method = #MethodName
OPEN RequestHeader
FETCH NEXT FROM RequestHeader
INTO #HeaderKey, #HeaderValue
WHILE ##FETCH_STATUS = 0
BEGIN
Set #ErrorCode = -800
--Select #HeaderKey, #HeaderValue, #MethodName
Exec #hResult = sp_OAMethod #objXmlHttp, 'setRequestHeader', Null, #HeaderKey, #HeaderValue
IF #hResult <> 0
BEGIN
Set #ErrorCode = -900
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = 'SetRequestHeader failed',
MedthodName = #MethodName
RaisError (N'SetRequestHeader failed.',16,1);
END
FETCH NEXT FROM RequestHeader
INTO #HeaderKey, #HeaderValue
END
CLOSE RequestHeader
DEALLOCATE RequestHeader
*/
Set #ErrorCode = -1000
-- send the request
Exec #hResult = sp_OAMethod #objXmlHttp, N'send', Null, #RequestBody
IF (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'Send failed',
MedthodName = #MethodName
RaisError (N'Send failed.',16,1);
End--if
Declare #StatusText varchar(1000), #Status varchar(1000)
Set #ErrorCode = -1100
-- Get status text
Exec sp_OAGetProperty #objXmlHttp, N'StatusText', #StatusText out
Exec sp_OAGetProperty #objXmlHttp, N'Status', #Status out
Select #Status As Status, #StatusText As statusText, #MethodName As MethodName
-- Get response text
Declare #Json Table (Result ntext)
Declare #Xml xml
Set #ErrorCode = -1200
Insert #Json(Result)
Exec #hResult = dbo.sp_OAGetProperty #objXmlHttp, N'ResponseText'
Set #ErrorCode = -1300
--Exec #hResult = dbo.sp_OAGetProperty #objXmlHttp, N'ResponseText', #ResponseText out
IF (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'ResponseText failed',
MedthodName = #MethodName
RaisError (N'ResponseText failed.',16,1);
END--if
Set #ErrorCode = -1400
--Set #ResponseText=Replicate(Convert(varchar(max),N'1'),1000000)
if (IsNull(#SoapAction,'')!='') Begin
Select #Xml=CAST(Replace(Replace(Replace(Cast(Result As nvarchar(max)),N'utf-8',N'utf-16'),N'.0,',N','),N'.00,',N',') As XML)
From #Json
Set #ErrorCode = -1500
Select #ResponseText = x.Rec.query(N'./*').value('.',N'nvarchar(max)')
From #Xml.nodes(N'.') as x(Rec)
End--if
Else Begin
Select #ResponseText= Result From #Json
End--Else
Set #ErrorCode = -1600
--Export To File
if (IsNull(#ExportToFile,'')!='') Begin
Declare #objToFile int
Declare #FileID int
Set #ErrorCode = -1700
--Create Object
Exec #hResult = sp_OACreate 'Scripting.FileSystemObject', #objToFile OUT
IF (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'Create failed Scripting.FileSystemObject',
MedthodName = #MethodName
RaisError (N'Create failed Scripting.FileSystemObject.',16,1);
End--if
Set #ErrorCode = -1800
--Create Or Open File
Exec #hResult = sp_OAMethod #objToFile, 'OpenTextFile' , #FileID OUT, #ExportToFile,2,1,-1
if (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'OpenTextFile failed',
MedthodName = #MethodName
RaisError (N'OpenTextFile failed.',16,1);
End--if
Set #ErrorCode = -1900
--Write Data To File
Exec #hResult = sp_OAMethod #FileID, 'Write', Null, #ResponseText
if (#hResult <> 0 ) Begin
Exec sp_OAGetErrorInfo #objXmlHttp, #source OUT, #desc OUT
Select hResult = convert(varbinary(4), #hResult),
source = #source,
description = #desc,
FailPoint = N'Write To File failed',
MedthodName = #MethodName
RaisError (N'Write To File failed.',16,1);
End--if
Set #ErrorCode = -2000
--Close File
Exec sp_OAMethod #FileID, 'Close'
--Delete Objects
Exec sp_OADestroy #FileID
Exec sp_OADestroy #objToFile
End--if
Set #ErrorCode = 0
/*If (##TranCount > 0)
Commit Transaction stp_HttpRequest*/
End Try
Begin Catch
/*If (##TranCount > 0)
Rollback Transaction stp_HttpRequest*/
Exec [dbo].[stp_GetErrorInfo]
End Catch
Exec sp_OADestroy #objXmlHttp
Return #ErrorCode
GO
--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//
--Example For Run Soap WebService
DECLARE #RC int
DECLARE #URI varchar(max)
DECLARE #MethodName sysname
DECLARE #RequestBody nvarchar(max)
DECLARE #SoapAction varchar(500)
DECLARE #UserName sysname=''
DECLARE #Password sysname=''
DECLARE #ResponseText nvarchar(max)
DECLARE #intA nvarchar(10)
DECLARE #intB nvarchar(10)
Set #intA = N'100'
Set #intB = N'200'
Set #URI = N'http://www.dneonline.com/calculator.asmx'
Set #MethodName = N'POST'
Set #RequestBody =
N'<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>
<Add xmlns="http://tempuri.org/"><intA>'+#intA+'</intA><intB>'+#intB+'</intB></Add>
</soap:Body>
</soap:Envelope>'
Set #SoapAction = N'http://tempuri.org/Add'
EXECUTE #RC = [dbo].[stp_HttpRequest]
#URI
,#MethodName
,#RequestBody
,#SoapAction
,#UserName
,#Password
,#ResponseText OUTPUT
Print #ResponseText
Print Len(#ResponseText)
Go
--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//
--Example For Feach Data From Website
DECLARE #RC int
DECLARE #URI varchar(max)
DECLARE #MethodName sysname
DECLARE #RequestBody nvarchar(max)
DECLARE #SoapAction varchar(500)
DECLARE #UserName sysname
DECLARE #Password sysname
DECLARE #ResponseText nvarchar(max)
Declare #ExportToFile nvarchar(max)
Set #URI = N'https://stackoverflow.com/questions/17407338/how-can-i-make-http-request-from-sql-server'
Set #MethodName = N'GET'
Set #RequestBody = N''
Set #SoapAction = N''
Set #ExportToFile = N'C:\Temp\Export\{RandomFileName}.html'
EXECUTE #RC = [dbo].[stp_HttpRequest]
#URI
,#MethodName
,#RequestBody
,#SoapAction
,#UserName
,#Password
,#ResponseText OUTPUT
,#ExportToFile
Print #ResponseText
Print Len(#ResponseText)
Go