Why is there a deadlock between two parallel executions of identical transactions? - sql-server

I have an application that uses an SQL transaction to make updates to the msdb database on SQL Server. This transaction is executed periodically, at irregular intervals. SQL Server 2012 (SP4) is used. After a while, SQL Server reports deadlocks on msdb.dbo.backupset table, and the only participants are the processes that execute the mentioned SQL transaction
Below is a functional example of the transaction, having the arguments replaced with example values so that it can be readily executed on msdb. The application passes new arguments with each call of the transaction.
BEGIN TRAN UpdateMediaTables
DECLARE #SqlVersion int
DECLARE #LogDevName nvarchar(512)
DECLARE #MediaSetId int
DECLARE #FamilySequenceNumber tinyint
DECLARE #MaxFamilySequence tinyint
DECLARE #Mirror tinyint
DECLARE #BackupFileName nvarchar(1024)
DECLARE #BackupFileNumber int
DECLARE #MediaFamilyCount int
DECLARE #MirrorCount int
DECLARE #CompressedSize numeric(20, 0)
DECLARE #sql as nvarchar(4000)
SET #SqlVersion = ##microsoftversion / 0x1000000
SET #MediaSetId = 3498233
SET #BackupFileNumber = 1
SET #MediaFamilyCount = 1
SET #MirrorCount = 1
SET #CompressedSize = 378880
SELECT #LogDevName = name
FROM master..sysdevices AS sdev
WHERE phyname = #BackupFileName
SET #sql = N'UPDATE bs SET position = #BackupFileNumber, last_family_number = #MediaFamilyCount'
IF #SqlVersion > 9 -- 2008+
BEGIN
SET #sql = #sql + N', compressed_backup_size = #CompressedSize'
END
SET #sql = #sql + N' FROM msdb..backupset AS bs
WHERE media_set_id = #MediaSetId'
EXEC sp_executesql #sql, N'#MediaFamilyCount int, #BackupFileNumber int, #CompressedSize numeric(20, 0), #MediaSetId int', #BackupFileNumber = #BackupFileNumber,#MediaFamilyCount = #MediaFamilyCount, #CompressedSize = #CompressedSize, #MediaSetId = #MediaSetId
UPDATE bms
SET media_family_count = #MediaFamilyCount, mirror_count = #MirrorCount
FROM msdb..backupmediaset AS bms
WHERE media_set_id = #MediaSetId
-- All bmf's
SET #FamilySequenceNumber = 1
SET #BackupFileName = N'\\testcase\Test_TLog_20211121180001.trn'
SET #Mirror = 0
UPDATE bmf
SET bmf.physical_device_name = #BackupFileName
FROM msdb..backupmediafamily AS bmf
WHERE bmf.media_set_id = #MediaSetId
AND bmf.family_sequence_number = #FamilySequenceNumber
AND bmf.mirror = #Mirror
UPDATE bmf
SET bmf.logical_device_name = #LogDevName
FROM msdb..backupmediafamily AS bmf
WHERE bmf.media_set_id = #MediaSetId
AND bmf.family_sequence_number = #FamilySequenceNumber
AND bmf.mirror = #Mirror
SET #MaxFamilySequence = 1
DELETE FROM msdb..backupmediafamily WITH (ROWLOCK)
WHERE media_set_id = #MediaSetId AND family_sequence_number > #MaxFamilySequence
COMMIT TRAN UpdateMediaTables
Here is the xml for the deadlock graph:
<deadlock>
<victim-list>
<victimProcess id="process2d890c8"/>
</victim-list>
<process-list>
<process id="process2d890c8" taskpriority="-5" logused="0" waitresource="PAGE: 4:1:8623 " waittime="1550" ownerId="1566457106" transactionname="UpdateMediaTables" lasttranstarted="2021-12-21T15:00:05.697" XDES="0xb16d09b80" lockMode="U" schedulerid="8" kpid="19856" status="suspended" spid="488" sbid="0" ecid="5" priority="5" trancount="0" lastbatchstarted="2021-12-21T15:00:05.660" lastbatchcompleted="2021-12-21T15:00:05.633" lastattention="1900-01-01T00:00:00.633" clientapp="Demo" hostname="AA-SQL1" hostpid="14200" isolationlevel="read uncommitted (1)" xactid="1566457106" currentdb="1" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="190" sqlhandle="0x020000000aac851a57d841f58dc63ba4bbe4b4059b68c6ab0000000000000000000000000000000000000000">
UPDATE bs SET position = #BackupFileNumber, last_family_number = #MediaFamilyCount, compressed_backup_size = #CompressedSize FROM msdb..backupset AS bs
WHERE media_set_id = #MediaSetId </frame>
<frame procname="mssqlsystemresource.sys.sp_executesql" line="1" stmtstart="-1" sqlhandle="0x0400ff7f427f99d9010000000000000000000000000000000000000000000000000000000000000000000000">
sp_executesql </frame>
<frame procname="adhoc" line="36" stmtstart="1996" stmtend="2528" sqlhandle="0x02000000a5af092360e1ef5edb55dab1b8cfba609a9b02e50000000000000000000000000000000000000000">
EXEC sp_executesql #sql, N'#MediaFamilyCount int, #BackupFileNumber int, #CompressedSize numeric(20, 0), #MediaSetId int', #BackupFileNumber = #BackupFileNumber,#MediaFamilyCount = #MediaFamilyCount, #CompressedSize = #CompressedSize, #MediaSetId = #MediaSetId </frame>
</executionStack>
<inputbuf>
BEGIN TRAN UpdateMediaTables
DECLARE #SqlVersion int
DECLARE #LogDevName nvarchar(512)
DECLARE #MediaSetId int
DECLARE #FamilySequenceNumber tinyint
DECLARE #MaxFamilySequence tinyint
DECLARE #Mirror tinyint
DECLARE #BackupFileName nvarchar(1024)
DECLARE #BackupFileNumber int
DECLARE #MediaFamilyCount int
DECLARE #MirrorCount int
DECLARE #CompressedSize numeric(20, 0)
DECLARE #sql as nvarchar(4000)
SET #SqlVersion = ##microsoftversion / 0x1000000
SET #MediaSetId = 566952
SET #BackupFileNumber = 1
SET #MediaFamilyCount = 1
SET #MirrorCount = 1
SET #CompressedSize = 156160
SELECT #LogDevName = name
FROM master..sysdevices AS sdev
WHERE phyname = #BackupFileName
SET #sql = N'UPDATE bs SET position = #BackupFileNumber, last_family_number = #MediaFamilyCount'
IF #SqlVersion > 9 -- 2008+
BEGIN
SET #sql = #sql + N', compressed_backup_size = #CompressedSize'
END
SET #sql = #sql + N' FROM msdb..backupset AS bs
WHERE media_set_id = #MediaSetId'
EXEC sp_executesql #sql, </inputbuf>
</process>
<process id="process2daa928" taskpriority="-5" logused="0" waitresource="PAGE: 4:1:9263 " waittime="1550" ownerId="1566457106" transactionname="UpdateMediaTables" lasttranstarted="2021-12-21T15:00:05.697" XDES="0x14b82acbd0" lockMode="U" schedulerid="1" kpid="8248" status="suspended" spid="488" sbid="0" ecid="6" priority="5" trancount="0" lastbatchstarted="2021-12-21T15:00:05.660" lastbatchcompleted="2021-12-21T15:00:05.633" lastattention="1900-01-01T00:00:00.633" clientapp="Demo" hostname="AA-SQL1" hostpid="14200" isolationlevel="read uncommitted (1)" xactid="1566457106" currentdb="1" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="190" sqlhandle="0x020000000aac851a57d841f58dc63ba4bbe4b4059b68c6ab0000000000000000000000000000000000000000">
UPDATE bs SET position = #BackupFileNumber, last_family_number = #MediaFamilyCount, compressed_backup_size = #CompressedSize FROM msdb..backupset AS bs
WHERE media_set_id = #MediaSetId </frame>
<frame procname="mssqlsystemresource.sys.sp_executesql" line="1" stmtstart="-1" sqlhandle="0x0400ff7f427f99d9010000000000000000000000000000000000000000000000000000000000000000000000">
sp_executesql </frame>
<frame procname="adhoc" line="36" stmtstart="1996" stmtend="2528" sqlhandle="0x02000000a5af092360e1ef5edb55dab1b8cfba609a9b02e50000000000000000000000000000000000000000">
EXEC sp_executesql #sql, N'#MediaFamilyCount int, #BackupFileNumber int, #CompressedSize numeric(20, 0), #MediaSetId int', #BackupFileNumber = #BackupFileNumber,#MediaFamilyCount = #MediaFamilyCount, #CompressedSize = #CompressedSize, #MediaSetId = #MediaSetId </frame>
</executionStack>
<inputbuf>
BEGIN TRAN UpdateMediaTables
DECLARE #SqlVersion int
DECLARE #LogDevName nvarchar(512)
DECLARE #MediaSetId int
DECLARE #FamilySequenceNumber tinyint
DECLARE #MaxFamilySequence tinyint
DECLARE #Mirror tinyint
DECLARE #BackupFileName nvarchar(1024)
DECLARE #BackupFileNumber int
DECLARE #MediaFamilyCount int
DECLARE #MirrorCount int
DECLARE #CompressedSize numeric(20, 0)
DECLARE #sql as nvarchar(4000)
SET #SqlVersion = ##microsoftversion / 0x1000000
SET #MediaSetId = 566952
SET #BackupFileNumber = 1
SET #MediaFamilyCount = 1
SET #MirrorCount = 1
SET #CompressedSize = 156160
SELECT #LogDevName = name
FROM master..sysdevices AS sdev
WHERE phyname = #BackupFileName
SET #sql = N'UPDATE bs SET position = #BackupFileNumber, last_family_number = #MediaFamilyCount'
IF #SqlVersion > 9 -- 2008+
BEGIN
SET #sql = #sql + N', compressed_backup_size = #CompressedSize'
END
SET #sql = #sql + N' FROM msdb..backupset AS bs
WHERE media_set_id = #MediaSetId'
EXEC sp_executesql #sql, </inputbuf>
</process>
<process id="process2bb4558" taskpriority="-5" logused="328" waitresource="PAGE: 4:1:9263 " waittime="948" ownerId="1566456428" transactionname="UpdateMediaTables" lasttranstarted="2021-12-21T15:00:04.410" XDES="0x14981ffb80" lockMode="U" schedulerid="7" kpid="19408" status="suspended" spid="470" sbid="0" ecid="7" priority="5" trancount="0" lastbatchstarted="2021-12-21T15:00:04.393" lastbatchcompleted="2021-12-21T15:00:04.393" lastattention="1900-01-01T00:00:00.393" clientapp="Demo" hostname="AA-SQL1" hostpid="14732" isolationlevel="read uncommitted (1)" xactid="1566456428" currentdb="1" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="190" sqlhandle="0x020000000aac851a57d841f58dc63ba4bbe4b4059b68c6ab0000000000000000000000000000000000000000">
UPDATE bs SET position = #BackupFileNumber, last_family_number = #MediaFamilyCount, compressed_backup_size = #CompressedSize FROM msdb..backupset AS bs
WHERE media_set_id = #MediaSetId </frame>
<frame procname="mssqlsystemresource.sys.sp_executesql" line="1" stmtstart="-1" sqlhandle="0x0400ff7f427f99d9010000000000000000000000000000000000000000000000000000000000000000000000">
sp_executesql </frame>
<frame procname="adhoc" line="36" stmtstart="1996" stmtend="2528" sqlhandle="0x02000000a9093d2c0a0d22ed2f73dc20e182fd1d912553b10000000000000000000000000000000000000000">
EXEC sp_executesql #sql, N'#MediaFamilyCount int, #BackupFileNumber int, #CompressedSize numeric(20, 0), #MediaSetId int', #BackupFileNumber = #BackupFileNumber,#MediaFamilyCount = #MediaFamilyCount, #CompressedSize = #CompressedSize, #MediaSetId = #MediaSetId </frame>
</executionStack>
<inputbuf>
BEGIN TRAN UpdateMediaTables
DECLARE #SqlVersion int
DECLARE #LogDevName nvarchar(512)
DECLARE #MediaSetId int
DECLARE #FamilySequenceNumber tinyint
DECLARE #MaxFamilySequence tinyint
DECLARE #Mirror tinyint
DECLARE #BackupFileName nvarchar(1024)
DECLARE #BackupFileNumber int
DECLARE #MediaFamilyCount int
DECLARE #MirrorCount int
DECLARE #CompressedSize numeric(20, 0)
DECLARE #sql as nvarchar(4000)
SET #SqlVersion = ##microsoftversion / 0x1000000
SET #MediaSetId = 566948
SET #BackupFileNumber = 1
SET #MediaFamilyCount = 1
SET #MirrorCount = 1
SET #CompressedSize = 259072
SELECT #LogDevName = name
FROM master..sysdevices AS sdev
WHERE phyname = #BackupFileName
SET #sql = N'UPDATE bs SET position = #BackupFileNumber, last_family_number = #MediaFamilyCount'
IF #SqlVersion > 9 -- 2008+
BEGIN
SET #sql = #sql + N', compressed_backup_size = #CompressedSize'
END
SET #sql = #sql + N' FROM msdb..backupset AS bs
WHERE media_set_id = #MediaSetId'
EXEC sp_executesql #sql, </inputbuf>
</process>
<process id="process2daacf8" taskpriority="-5" logused="328" waitresource="PAGE: 4:1:8623 " waittime="972" ownerId="1566456428" transactionname="UpdateMediaTables" lasttranstarted="2021-12-21T15:00:04.410" XDES="0x14b82ace80" lockMode="U" schedulerid="1" kpid="7048" status="suspended" spid="470" sbid="0" ecid="4" priority="5" trancount="0" lastbatchstarted="2021-12-21T15:00:04.393" lastbatchcompleted="2021-12-21T15:00:04.393" lastattention="1900-01-01T00:00:00.393" clientapp="Demo" hostname="AA-SQL1" hostpid="14732" isolationlevel="read uncommitted (1)" xactid="1566456428" currentdb="1" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="190" sqlhandle="0x020000000aac851a57d841f58dc63ba4bbe4b4059b68c6ab0000000000000000000000000000000000000000">
UPDATE bs SET position = #BackupFileNumber, last_family_number = #MediaFamilyCount, compressed_backup_size = #CompressedSize FROM msdb..backupset AS bs
WHERE media_set_id = #MediaSetId </frame>
<frame procname="mssqlsystemresource.sys.sp_executesql" line="1" stmtstart="-1" sqlhandle="0x0400ff7f427f99d9010000000000000000000000000000000000000000000000000000000000000000000000">
sp_executesql </frame>
<frame procname="adhoc" line="36" stmtstart="1996" stmtend="2528" sqlhandle="0x02000000a9093d2c0a0d22ed2f73dc20e182fd1d912553b10000000000000000000000000000000000000000">
EXEC sp_executesql #sql, N'#MediaFamilyCount int, #BackupFileNumber int, #CompressedSize numeric(20, 0), #MediaSetId int', #BackupFileNumber = #BackupFileNumber,#MediaFamilyCount = #MediaFamilyCount, #CompressedSize = #CompressedSize, #MediaSetId = #MediaSetId </frame>
</executionStack>
<inputbuf>
BEGIN TRAN UpdateMediaTables
DECLARE #SqlVersion int
DECLARE #LogDevName nvarchar(512)
DECLARE #MediaSetId int
DECLARE #FamilySequenceNumber tinyint
DECLARE #MaxFamilySequence tinyint
DECLARE #Mirror tinyint
DECLARE #BackupFileName nvarchar(1024)
DECLARE #BackupFileNumber int
DECLARE #MediaFamilyCount int
DECLARE #MirrorCount int
DECLARE #CompressedSize numeric(20, 0)
DECLARE #sql as nvarchar(4000)
SET #SqlVersion = ##microsoftversion / 0x1000000
SET #MediaSetId = 566948
SET #BackupFileNumber = 1
SET #MediaFamilyCount = 1
SET #MirrorCount = 1
SET #CompressedSize = 259072
SELECT #LogDevName = name
FROM master..sysdevices AS sdev
WHERE phyname = #BackupFileName
SET #sql = N'UPDATE bs SET position = #BackupFileNumber, last_family_number = #MediaFamilyCount'
IF #SqlVersion > 9 -- 2008+
BEGIN
SET #sql = #sql + N', compressed_backup_size = #CompressedSize'
END
SET #sql = #sql + N' FROM msdb..backupset AS bs
WHERE media_set_id = #MediaSetId'
EXEC sp_executesql #sql, </inputbuf>
</process>
<process id="process12ee786188" taskpriority="-5" logused="10000" waittime="730" schedulerid="12" kpid="1808" status="suspended" spid="470" sbid="0" ecid="0" priority="5" trancount="2" lastbatchstarted="2021-12-21T15:00:04.393" lastbatchcompleted="2021-12-21T15:00:04.393" lastattention="1900-01-01T00:00:00.393" clientapp="Demo" hostname="AA-SQL1" hostpid="14732" loginname="DEMO\test" isolationlevel="read uncommitted (1)" xactid="1566456428" currentdb="1" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="190" sqlhandle="0x020000000aac851a57d841f58dc63ba4bbe4b4059b68c6ab0000000000000000000000000000000000000000">
UPDATE bs SET position = #BackupFileNumber, last_family_number = #MediaFamilyCount, compressed_backup_size = #CompressedSize FROM msdb..backupset AS bs
WHERE media_set_id = #MediaSetId </frame>
<frame procname="mssqlsystemresource.sys.sp_executesql" line="1" stmtstart="-1" sqlhandle="0x0400ff7f427f99d9010000000000000000000000000000000000000000000000000000000000000000000000">
sp_executesql </frame>
<frame procname="adhoc" line="36" stmtstart="1996" stmtend="2528" sqlhandle="0x02000000a9093d2c0a0d22ed2f73dc20e182fd1d912553b10000000000000000000000000000000000000000">
EXEC sp_executesql #sql, N'#MediaFamilyCount int, #BackupFileNumber int, #CompressedSize numeric(20, 0), #MediaSetId int', #BackupFileNumber = #BackupFileNumber,#MediaFamilyCount = #MediaFamilyCount, #CompressedSize = #CompressedSize, #MediaSetId = #MediaSetId </frame>
</executionStack>
<inputbuf>
BEGIN TRAN UpdateMediaTables
DECLARE #SqlVersion int
DECLARE #LogDevName nvarchar(512)
DECLARE #MediaSetId int
DECLARE #FamilySequenceNumber tinyint
DECLARE #MaxFamilySequence tinyint
DECLARE #Mirror tinyint
DECLARE #BackupFileName nvarchar(1024)
DECLARE #BackupFileNumber int
DECLARE #MediaFamilyCount int
DECLARE #MirrorCount int
DECLARE #CompressedSize numeric(20, 0)
DECLARE #sql as nvarchar(4000)
SET #SqlVersion = ##microsoftversion / 0x1000000
SET #MediaSetId = 566948
SET #BackupFileNumber = 1
SET #MediaFamilyCount = 1
SET #MirrorCount = 1
SET #CompressedSize = 259072
SELECT #LogDevName = name
FROM master..sysdevices AS sdev
WHERE phyname = #BackupFileName
SET #sql = N'UPDATE bs SET position = #BackupFileNumber, last_family_number = #MediaFamilyCount'
IF #SqlVersion > 9 -- 2008+
BEGIN
SET #sql = #sql + N', compressed_backup_size = #CompressedSize'
END
SET #sql = #sql + N' FROM msdb..backupset AS bs
WHERE media_set_id = #MediaSetId'
EXEC sp_executesql #sql, </inputbuf>
</process>
</process-list>
<resource-list>
<pagelock fileid="1" pageid="8623" dbid="4" subresource="FULL" objectname="msdb.dbo.backupset" id="lock5e1d530780" mode="U" associatedObjectId="72057594045595648">
<owner-list>
<owner id="process12ee786188" mode="U"/>
</owner-list>
<waiter-list>
<waiter id="process2d890c8" mode="U" requestType="wait"/>
</waiter-list>
</pagelock>
<pagelock fileid="1" pageid="9263" dbid="4" subresource="FULL" objectname="msdb.dbo.backupset" id="lockf1b4c0980" mode="U" associatedObjectId="72057594045595648">
<owner-list>
<owner id="process12ee786188" mode="U"/>
</owner-list>
<waiter-list>
<waiter id="process2daa928" mode="U" requestType="wait"/>
</waiter-list>
</pagelock>
<pagelock fileid="1" pageid="9263" dbid="4" subresource="FULL" objectname="msdb.dbo.backupset" id="lockf1b4c0980" mode="U" associatedObjectId="72057594045595648">
<owner-list>
<owner id="process2daa928" mode="U" requestType="wait"/>
</owner-list>
<waiter-list>
<waiter id="process2bb4558" mode="U" requestType="wait"/>
</waiter-list>
</pagelock>
<pagelock fileid="1" pageid="8623" dbid="4" subresource="FULL" objectname="msdb.dbo.backupset" id="lock5e1d530780" mode="U" associatedObjectId="72057594045595648">
<owner-list>
<owner id="process2d890c8" mode="U" requestType="wait"/>
</owner-list>
<waiter-list>
<waiter id="process2daacf8" mode="U" requestType="wait"/>
</waiter-list>
</pagelock>
<exchangeEvent id="Pipe25c250400" WaitType="e_waitPipeGetRow" nodeId="2">
<owner-list>
<owner id="process2daacf8"/>
<owner id="process2bb4558"/>
</owner-list>
<waiter-list>
<waiter id="process12ee786188"/>
</waiter-list>
</exchangeEvent>
</resource-list>
</deadlock>
I don't see how this situation could lead to a deadlock. Even if the two processes coincide in parallel, the two transactions are identical and therefore execute their queries in the same sequential order. Furthermore, the query that updates the backupset table doesn't have who to deadlock with, since it is the only one in the entire transaction that queries this table. Lock yes, but not deadlock. Can someone please help me understand how this deadlock situation is possible?

Instead of diagnosing this one, I would just hit the "easy button", and serialize the transactions with an application lock:
BEGIN TRAN UpdateMediaTables
exec sp_getapplock 'UpdateMediaTables', 'Exclusive'
. . .
Then the second session will be blocked before acquiring any locks until the first is complete.

Related

REST in SQL Server [duplicate]

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&param2=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;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

SQL Server stored procedure to JSON error

I am trying to write the following stored procedure:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spInsertAudit]
(#val1 VARCHAR(100),
#val2 VARCHAR(200))
AS
BEGIN TRY
DECLARE #return_value varchar(max)
/************************************/
/* The Query */
/************************************/
EXEC [dbo].[SerializeJSON]
'INSERT INTO tLogin (EMP, LoginInTime)
VALUES (#val1, #val2)'
END TRY
BEGIN CATCH
/************************************/
/* Get Error results back */
/************************************/
EXEC [dbo].[SerializeJSON]
'SELECT ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage'
END CATCH
The SerializeJSON stored procedure (found here) is this:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[SerializeJSON]
(#ParameterSQL AS VARCHAR(MAX))
AS
BEGIN
DECLARE #SQL NVARCHAR(MAX)
DECLARE #XMLString VARCHAR(MAX)
DECLARE #XML XML
DECLARE #Paramlist NVARCHAR(1000)
SET #Paramlist = N'#XML XML OUTPUT'
SET #SQL = 'WITH PrepareTable (XMLString)'
SET #SQL = #SQL + 'AS('
SET #SQL = #SQL + #ParameterSQL + 'FOR XML RAW,TYPE,ELEMENTS'
SET #SQL = #SQL + ')'
SET #SQL = #SQL + 'SELECT #XML=[XMLString]FROM[PrepareTable]'
EXEC sp_executesql #SQL
, #Paramlist
, #XML = #XML OUTPUT
SET #XMLString = CAST(#XML AS VARCHAR(MAX))
DECLARE #JSON VARCHAR(MAX)
DECLARE #Row VARCHAR(MAX)
DECLARE #RowStart INT
DECLARE #RowEnd INT
DECLARE #FieldStart INT
DECLARE #FieldEnd INT
DECLARE #KEY VARCHAR(MAX)
DECLARE #Value VARCHAR(MAX)
DECLARE #StartRoot VARCHAR(100);
SET #StartRoot = '<row>'
DECLARE #EndRoot VARCHAR(100);
SET #EndRoot = '</row>'
DECLARE #StartField VARCHAR(100);
SET #StartField = '<'
DECLARE #EndField VARCHAR(100);
SET #EndField = '>'
SET #RowStart = CharIndex(#StartRoot, #XMLString, 0)
SET #JSON = ''
WHILE #RowStart > 0
BEGIN
SET #RowStart = #RowStart + Len(#StartRoot)
SET #RowEnd = CharIndex(#EndRoot, #XMLString, #RowStart)
SET #Row = SubString(#XMLString, #RowStart, #RowEnd - #RowStart)
SET #JSON = #JSON + '{'
-- for each row
SET #FieldStart = CharIndex(#StartField, #Row, 0)
WHILE #FieldStart > 0
BEGIN
-- parse node key
SET #FieldStart = #FieldStart + Len(#StartField)
SET #FieldEnd = CharIndex(#EndField, #Row, #FieldStart)
SET #KEY = SubString(#Row, #FieldStart, #FieldEnd - #FieldStart)
SET #JSON = #JSON + '"' + #KEY + '":'
-- parse node value
SET #FieldStart = #FieldEnd + 1
SET #FieldEnd = CharIndex('</', #Row, #FieldStart)
SET #Value = SubString(#Row, #FieldStart, #FieldEnd - #FieldStart)
SET #JSON = #JSON + '"' + #Value + '",'
SET #FieldStart = #FieldStart + Len(#StartField)
SET #FieldEnd = CharIndex(#EndField, #Row, #FieldStart)
SET #FieldStart = CharIndex(#StartField, #Row, #FieldEnd)
END
IF LEN(#JSON) > 0
SET #JSON = SubString(#JSON, 0, LEN(#JSON))
SET #JSON = #JSON + '},'
--/ for each row
SET #RowStart = CharIndex(#StartRoot, #XMLString, #RowEnd)
END
IF LEN(#JSON) > 0
SET #JSON = SubString(#JSON, 0, LEN(#JSON))
SET #JSON = '[' + #JSON + ']'
SELECT #JSON
END
When I execute the spInsertAudit stored procedure, I get this error:
Msg 102, Level 15, State 1, Line 8
Incorrect syntax near 'XML'.
So it did write to that table but for some reason it's not returning the JSON and having that error above....

How to set the result of a stored procedure to a variable

I am calling a stored procedure like this:
EXEC usp123 #F1 = 1, #F2 = 'A', #F3 = 5
DECLARE #Result int
SET #Result = (EXEC usp123 #F1 = 1, #F2 = 'A', #F3 = 5)
How do I assign a variable to the output of this stored procedure as the above syntax does not work ..
The last line should be
Declare #Result Int
EXEC #Result = usp123 #F1 = 1, #F2 = 'A', #F3 = 5
--Check this... your answer is in the last sentence.
DECLARE #IntVariable int;
DECLARE #SQLString nvarchar(500);
DECLARE #ParmDefinition nvarchar(500);
DECLARE #max_title varchar(30);
SET #IntVariable = 197;
SET #SQLString = N'SELECT #max_titleOUT = max(JobTitle)
FROM AdventureWorks2012.HumanResources.Employee
WHERE BusinessEntityID = #level';
SET #ParmDefinition = N'#level tinyint, #max_titleOUT varchar(30) OUTPUT';
EXECUTE sp_executesql #SQLString, #ParmDefinition, #level = #IntVariable,
#max_titleOUT=#max_title OUTPUT;
SELECT #max_title;

SQL Server stored procedure date

I have a procedure which add new data in a table.
The name of the table is in the paramaters.
The error is
The data types varchar(max) and date are incompatible in the add operator.
The date field must be type date.
PROCEDURE
USE [ProposalBuilderDev]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[addLog]
-- Add the parameters for the stored procedure here
#table varchar(max),
#date date,
#version varchar(max),
#process varchar(max),
#level varchar(max),
#message varchar(max),
#stacktrace varchar(max),
#user varchar(max),
#environmentID varchar(max),
#UUID varchar(max),
#UDID varchar(max),
#transactionID int,
#new_identity int OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
DECLARE #sql NVARCHAR(MAX);
SET #sql = 'INSERT INTO dbo.' + #table + '([Timestamp], [Version],Process,[Level],[Message],StackTrace,[User],EnvironmentID,UUID,UDID,TransactionID) VALUES (' + #date + ',' + #version + ',' + #process + ','+ #level + ','+ #message + ','+ #stacktrace + ','+ #user + ','+ #environmentID + ','+ #UUID + ','+ #UDID + ',' + #transactionID + ')'
EXEC #sql
SET #new_identity = SCOPE_IDENTITY();
END
Pleas try to use CAST()
... + CAST(#date AS VARCHAR(MAX) + ...
Also, using sp_executesql would be a better and safer approach.
DECLARE #SQL NVARCHAR(MAX);
SET #SQL = ' INSERT INTO dbo.' + #Table;
SET #SQL += ' ([Timestamp], [Version],Process,[Level],[Message],StackTrace,[User],EnvironmentID,UUID,UDID,TransactionID)';
SET #SQL += ' VALUES';
SET #SQL += ' (#p0, #p1, #p2, #p3, #p4, #p5, #p6, #p7, #p8, #p9, #p10);';
EXECUTE sp_executesql
#SQL
, N'#p0 DATE, #p1 VARCHAR(MAX), #p2 VARCHAR(MAX), #p3 VARCHAR(MAX), #p4 VARCHAR(MAX), #p5 VARCHAR(MAX), #p6 VARCHAR(MAX), #p7 VARCHAR(MAX), #p8 VARCHAR(MAX), #p9 VARCHAR(MAX), #p10 VARCHAR(MAX)'
, #p0 = #date
, #p1 = #version
, #p2 = #process
, #p3 = #level
, #p4 = #message
, #p5 = #stacktrace
, #p6 = #user
, #p7 = #environmentID
, #p8 = #UUID
, #p9 = #UDID
, #p10 = #transactionID;
Just specify correct column data types in 3rd line.

How can I make HTTP request from SQL server?

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&param2=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;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

Resources