Can't use sp_configure in remote Sql server - sql-server

I used sq_configure to use OLE automation process to send http request from SQL server like
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
and then I built one stored procedure called HTTP_Request as shown below
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
and I called the stored procedure as
USE [master]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[HTTP_Request]
#sUrl = N'url'
SELECT 'Return Value' = #return_value
GO
It was working fine in my local sql server, I can able to send the http request from database.
Now My problem is I got access to remote sql server where I suppose to use the same thing as I did in my local system, but when I try to execute sp_configure I can't. I got error as
could not find stored procedure 'sp_configure'
any idea?
Is this problem with access restriction?

You can't run sp_configure on WASD, sorry. And even if you could, you would not be able to invoke OA methods. You will need to find another way to hit your web page (e.g. hit it from your application instead of from a stored procedure - arguably where it should happen anyway).

Related

SQL Server Woocommerce API connection gives NULL when getting products, works fine with orders

I am trying to set up a connection between a external SQL Server Database and the Woocommerce API.
The goal is to communicate between 2 websites, where they exchange data, the external website will send a POST request to Woocommerce to create a product, then GET the list of products to select the latest added one and then uses that product ID to create a add to cart link which will put the product into the Cart.
Now here is my code :
DECLARE #contentType NVARCHAR(64);
DECLARE #ret INT;
DECLARE #responseText NVARCHAR(4000);
DECLARE #status NVARCHAR(32);
DECLARE #statusText NVARCHAR(32);
DECLARE #token INT;
DECLARE #url NVARCHAR(256);
SET #contentType = 'application/json';
set #url = 'https://mywebsite.com/wp-json/wc/v3/products/?consumer_key=mykey&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1458225139&oauth_nonce=nVq4rX&consumer_secret=mysecret&oauth_signature=kzoVx%20VYSWlLbRpi3f8222222%3D'
EXEC #ret = sp_OACreate 'WinHttp.WinHttpRequest.5.1', #token OUT;
EXEC #ret = sp_OAMethod #token, 'open', NULL, 'GET', #url, 'false';
EXEC #ret = sp_OAMethod #token, 'setRequestHeader', NULL, 'Content-type', #contentType;
EXEC #ret = sp_OAMethod #token, 'send', NULL;
EXEC #ret = sp_OAGetProperty #token, 'status', #status OUT;
EXEC #ret = sp_OAGetProperty #token, 'statusText', #statusText OUT;
EXEC #ret = sp_OAGetProperty #token, 'responseText', #responseText OUT;
EXEC #ret = sp_OADestroy #token;
RETURN #responseText;
When i return the status i get 200, which to my knowledge is the desirable status.
But when i return responseText i get null.
The infuriating part is when i replace products with orders i get a result as expected, but when getting the products it keeps saying NULL.
Please help, because i am losing the last few hairs on my head.
Also my boss insists on doing it by SQL Server..

SQL Server 2016 stored procedure to function

I've created a stored procedure that uses a temp table to take the massive results of a Bing maps XML and convert it to varchar so that I can use it to retrieve several fields. The reason for converting it to varchar was because the XML was too large for the sp_OAMethod and my variable was always blank.
set #serviceUrl = 'https://dev.virtualearth.net/REST/v1/Routes/Truck?wp.0=' + #ToAddress + '&wp.1=' + #FromAddress + '&vehicleHazardousMaterials=Flammable&output=xml&key=XXX-000-XXX'
Exec sp_OACreate 'MSXML2.XMLHTTP', #Object OUT;
Exec sp_OAMethod #Object, 'open', NULL, 'get',#serviceUrl, 'false'
Exec sp_OAMethod #Object, 'send'
Exec sp_OAMethod #Object, 'responseText', #ResponseText OUTPUT
exec #returnCode = sp_oamethod #Object, 'read', #ResponseText out, -1
Create table #tmp(dt xml)
insert into #tmp
exec #hr = sp_OAGetProperty #Object, 'responseXML.XML'
Set #ResponseText = Convert(varchar(max), (SELECT dt from #tmp))
Drop Table #tmp
select REPLACE(SUBSTRING(#ResponseText,PATINDEX('%<TravelDistance>%',#ResponseText),21),'<TravelDistance>','') Miles
,REPLACE(REPLACE(SUBSTRING(#ResponseText,PATINDEX('%<TravelDuration>%',#ResponseText),21),'<TravelDuration>',''),'<','')/60 TravelMinutes
Above is not the complete code; I've edited it severely to make it easier to read.
I'm sure there is a better way to do it but this works and it's very exciting.
However, the plan was to create a function that could be used along with other ad-hoc queries to retrieve the same data. Not possible as a function because of the temp table or populating a table from within the function.
So does anyone have a way to make this possible?
You really should use CLR for this. You're a long way from a correct stored procedure here, and the sp_OAxxx procedures are best avoided. You're not handling the return code correctly, you're using the wrong HTTP component, and not parsing the results using the SQL Server's XML parser. It may seem initially like a CLR implementation is more work, but maintaining code that uses sp_OAxxx stored procedures and COM interop will always be painful.
There are very few people who understand how this code works, how to change it, and whether it's safe and reliable. The next person to own your codebase is probably not one of those people. It's not good to have code like that in your project.
If you do use CLR, you still shouldn't use a function (although you technically can). You shouldn't perform any external access in the middle of a query.
Anyway here's some fixes to your existing approach:
declare #serviceURL varchar(max)
declare #returnCode int
declare #errorMessage nvarchar(max)
declare #Object int
declare #hr int
declare #key varchar(2000) = 'Aoj...nFS'
declare #FromAddress nvarchar(max) = '7000 N SH 161, Irving TX 75039'
declare #ToAddress nvarchar(max) = '8617 Garland Rd, Dallas, TX 75218'
set #serviceUrl = 'https://dev.virtualearth.net/REST/v1/Routes/Truck?wp.0=' + #ToAddress + '&wp.1=' + #FromAddress + '&vehicleHazardousMaterials=Flammable&output=xml&key=' + #key
exec #hr = sp_OACreate 'MSXML2.ServerXMLHTTP', #Object OUT;
IF #hr <> 0
begin
set #errorMessage = concat('sp_OACreate failed ', convert(varchar(20),cast(#hr as varbinary(4)),1));
throw 60000, #errorMessage, 1;
end;
begin try
Exec #hr = sp_OAMethod #Object, 'open', NULL, 'get',#serviceUrl, 'false'
IF #hr <> 0
begin
set #errorMessage = concat('open failed ', convert(varchar(20),cast(#hr as varbinary(4)),1));
throw 60000, #errorMessage, 1;
end;
Exec #hr = sp_OAMethod #Object, 'send'
IF #hr <> 0
begin
set #errorMessage = concat('send failed ', convert(varchar(20),cast(#hr as varbinary(4)),1));
throw 60000, #errorMessage, 1;
end;
declare #responseCode int;
Exec #hr = sp_OAGetProperty #Object, 'status', #responseCode out
IF #hr <> 0 or #responseCode <> 200
begin
set #errorMessage = concat('send failed hr:', convert(varchar(20),cast(#hr as varbinary(4)),1),' http response code: ', #responseCode);
throw 60000, #errorMessage, 1;
end;
declare #tmp table(doc xml)
insert into #tmp
exec #hr = sp_OAGetProperty #Object, 'ResponseXML.XML'
IF #hr <> 0
begin
set #errorMessage = concat('ResponseXML.XML failed ', convert(varchar(20),cast(#hr as varbinary(4)),1));
throw 60000, #errorMessage, 1;
end;
WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/search/local/ws/rest/v1')
select doc.value('(//TravelDistance)[1]', 'float') TravelDistance,
doc.value('(//DistanceUnit)[1]', 'nvarchar(20)') DistanceUnit,
doc.value('(//TravelDuration)[1]', 'float') TravelDuration,
doc.value('(//DurationUnit)[1]', 'nvarchar(20)') DurationUnit
from #tmp;
end try
begin catch
exec #hr = sp_OADestroy #Object ;
throw;
end catch

Consuming webservice by SQL Server procedure

I am using sql server 2016 to consume webservice through store procedure. I have a webservice in JSON returning the following:
["Name":"Rebecca","email":"rebecca#hotmail.com","ra":"12345"},
{"name":"Caroline","email":"caroline#hotmail.com","ra":"23456"},
{"name":"Vanessa","email":"vanessa#yahoo.com.br","ra":"99999"}]
I can consume it by passing a variable. If I leave my webservice to receive a parameter and pass it I can return the name and email of the student. But if I leave my webservice without the need to receive parameter and remove the procedure parameter pass and execute, my procedure returns null. What do I need to change in my code to be able to return the complete list of students my webservice exposes?
Here's my code:
create PROCEDURE webservice_parametros (#RA as varchar (5))
AS
BEGIN
DECLARE #OBJ INT;
DECLARE #URL VARCHAR(200);
DECLARE #RESPONSE VARCHAR(8000);
SET #URL = 'http://dominio:8080/v1/alunos/' + #RA
EXEC SP_OACREATE 'MSXML2.ServerXMLHttp', #OBJ out
EXEC SP_OAMETHOD #OBJ, 'OPEN', NULL, 'GET', #URL, FALSE
EXEC SP_OAMETHOD #OBJ, 'SEND'
exec SP_OAGETPROPERTY #OBJ, 'responseText', #RESPONSE out
EXEC SP_OADESTROY #OBJ
SELECT JSON_VALUE(#RESPONSE, '$.nome') as nome,
JSON_VALUE(#RESPONSE, '$.email') as email
END
execute webservice_parametros '12345'
My code that returns NULL
create PROCEDURE webservice
AS
BEGIN
DECLARE #OBJ INT;
DECLARE #URL VARCHAR(200);
DECLARE #RESPONSE VARCHAR(8000);
SET #URL = 'http://dominio:8080/v1/alunos/'
EXEC SP_OACREATE 'MSXML2.ServerXMLHttp', #OBJ out
EXEC SP_OAMETHOD #OBJ, 'OPEN', NULL, 'GET', #URL, FALSE
EXEC SP_OAMETHOD #OBJ, 'SEND'
exec SP_OAGETPROPERTY #OBJ, 'responseText', #RESPONSE out
EXEC SP_OADESTROY #OBJ
SELECT JSON_VALUE(#RESPONSE, '$.nome') as nome,
JSON_VALUE(#RESPONSE, '$.email') as email
END
execute webservice

Read binary data in TSQL through HTTP GET

I need to export some images into my SQL Server through HTTP URL.
I've found article about exporting of XML data:
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
Declare #Object as Int;
Declare #ResponseText as Varchar(8000);
Declare #Url as Varchar(MAX);
select #Url = 'http://somexml.com/xmlfile.xml'
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
--load into Xml
Declare #XmlResponse as xml;
select #ResponseText
Also during research I've found that I should use ADODB.Stream for binary data. But I can't figure out how to read this object using approach described above.
Is there a way for reading binary data in pure TSQL or I should use CLR for this?
Thanks a lot for helping.
I had the same question as you, and found how to do it!
Here is my sql to do it (it supports retrieval of text and binary data):
EXEC sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
EXEC sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
declare #xmlObject as int
declare #responseText as varchar(max)
declare #responseBody as varbinary(max)
declare #status as int
declare #url as varchar(2048)
select #url = 'http://someurl.com/someimage.jpg'
exec sp_OACreate 'MSXML2.XMLHTTP', #xmlObject OUT;
exec sp_OAMethod #xmlObject, 'open', NULL, 'get', #url, 'false'
exec sp_OAMethod #xmlObject, 'send'
exec sp_OAMethod #xmlObject, 'status', #status OUTPUT
exec sp_OAMethod #xmlObject, 'responsetext', #responseText OUTPUT
declare #responseTable as table ( body varbinary(max) )
INSERT INTO #responseTable exec sp_OAMethod #xmlObject, 'responsebody'
exec sp_OADestroy #xmlObject
select #status
select #responseText
select #responseBody=body from #responseTable
select #responseBody
Hope this helps somone out there :)

Http post SQL Server 2000 stored procedure

We are having trouble sending a http post via a stored procedure on SQL Server 2000. SQL is the only method we have to send the http post.
We are apparently not sending a [fin , ack] and the connection is not shutting down quick enough. can anyone tell me what the problem is?
CREATE procedure HTTP_POST( #sUrl varchar(200), #response varchar(8000) out)
As
Declare
#obj int
,#hr int
,#status int
,#msg varchar(255)
exec #hr = sp_OACreate 'MSXML2.ServerXMLHttp', #obj OUT
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, 'status', #status OUT
if #hr <>0 begin set #msg = 'sp_OAMethod read status failed' goto
eh
end
if #status <> 200 begin set #msg = 'sp_OAMethod http status ' +
str(#status) goto eh end
exec #hr = sp_OAGetProperty #obj, 'responseText', #response OUT
if #hr <>0 begin set #msg = 'sp_OAMethod read response failed' goto
eh end
exec #hr = sp_OADestroy #obj
return
eh:
exec #hr = sp_OADestroy #obj
return
GO
I call the stored procedure like so
exec HTTP_POST 'http://123.123.123.123/example.webservice?time=201205021000000'
I'm guessing the issue is with the underlying O/S (Windows); it's likely keeping the TCP connection open for an extended period of time after you dispose of the connection.
To verify, check netstat -a -p tcp before and after executing your sproc; look for a connection and see when it dies. I'd guess the connection disappears well after your sproc is done executing, sitting in a TIME_WAIT state. Windows will keep a connection alive for 2-4 minutes IIRC. One method to possibly counteract this is to add a custom HTTP header (Connection: Close), so that the remote server will close the connection after execution. Some "regular" code looks like this, you'll just need to adapt it to your SQL functions: serverXMLHTTP.setRequestHeader("Connection","Close");
If none of this works, I'd use Wireshark to track the connection and which packets are sent when to help isolate the issue. Good luck

Resources